I am trying to get a jQuery dataTable to behave in such a way that a user can select a row and then click a button (located elsewhere on the page, but not on the table or in it) and have a JS alert pop up.
Here is my dataTable:
$("#my-datatable").dataTable( {
"bProcessing" : true,
// Commenting out next line
//"sDom" : 't',
"sAjaxSource" : "some/url/on/my/server",
"sAjaxDataProp" : "",
"bDestroy" : true,
"fnServerData" : function(sSource, aoData, fnCallback) {
aoData.push({
"name" : "asking",
"value" : "yes"
});
request = $.ajax({
"dataType" : "json",
"type" : "GET",
"url" : sSource,
"data" : aoData,
"success" : fnCallback
});
},
"aoColumns" : [
{
"mDataProp" : "name"
},
{
"mDataProp" : "expr"
},
{
"mDataProp" : "seq"
}
]
});
Here is my button:
<div id="bam-btn-div">
<input type="button" id="bam-btn" value="BAM!" onclick="bam();"/>
</div>
When the user selects a row in the dataTable, and then clicks the button, I want the following function called:
function bam() {
alert("Deleting the selected row");
// Delete the selected row in the dataTable
}
Finally, the HTML table that the jQuery dataTable is attempting to populate:
<div id="datatable-div">
<table id="optconfig-datatable">
<thead>
<tr>
<th>Name</th>
<th>Expression</th>
<th>Sequence</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
I tried to follow the example here but couldn't get anything to work. Can anybody spot what configurations I need to add (to the dataTable and/or otherwise)? Thanks in advance!
You are using jQuery, you might as well stay on track.
$('#bam-btn').on('click', function(){
alert("BAM!");
});
On a side note, ID's must be unique, but I'm sure you know that, so make sure you're not trying to re-use the same ID over and over.
Moreover, if this element is added into the DOM after .ready() execution, you'll need to attach the event handler to a static parent element so it may delegate the click event properly.
$(document).on('click', '#bam-btn', function(){
alert("BAM");
});
I'll leave the above in place, I don't like to delete entire portions of my answer as you never know who may find it helpful in the future
First, we need to create a variable that's available to all scopes of all functions. This way, we can reference the variable to get a hold of the element we want to remove.
We should place this variable outside of the document ready function
var theRow = '';
$(document).ready(function(){
//existing code here
});
Now that we have a 'global scope' variable prepared, we can modify it and access it anytime.
var theRow = '';
$(document).ready(function(){
$('tr').click(function(){
//we need to store a unique piece of information about this row.
//Without much to go on, I'm going to rely on the index.
theRow = $(this).index();
});
$('#bam-btn').click(function(){
$('tr').eq(theRow).remove();
});
});
And here is your decent working jsFiddle as an example
For future users, and anyone else whom may find this useful
The :eq() selector provided by jQuery cannot leverage .querySelectorAll() to gain a decently large performance boost. Because of this, and for the time being, you should always use .eq() over :eq().
Please check that your:
function bam() {
alert("BAM!");
}
Is not in this statement:
$(document).ready(function() {
// STATEMENT
});
If your function is in the $(document).ready(), that means it's available only in that scope, in that particular function().
Move your code above or below the $(document).ready() statement, and your onclick event handler in your button will be able to find it and invoke it.
To delete a specific element from your data-table, try with this JavaScript:
$(document).ready(function() {
var oTable = $("#my-datatable").dataTable( {
"bProcessing" : true,
// Commenting out next line
//"sDom" : 't',
"sAjaxSource" : "some/url/on/my/server",
"sAjaxDataProp" : "",
"bDestroy" : true,
"fnServerData" : function(sSource, aoData, fnCallback) {
aoData.push({
"name" : "asking",
"value" : "yes"
});
request = $.ajax({
"dataType" : "json",
"type" : "GET",
"url" : sSource,
"data" : aoData,
"success" : fnCallback
});
},
"aoColumns" : [
{
"mDataProp" : "name"
},
{
"mDataProp" : "expr"
},
{
"mDataProp" : "seq"
}
]
});$("#my-datatable").dataTable( {
"bProcessing" : true,
// Commenting out next line
//"sDom" : 't',
"sAjaxSource" : "some/url/on/my/server",
"sAjaxDataProp" : "",
"bDestroy" : true,
"fnServerData" : function(sSource, aoData, fnCallback) {
aoData.push({
"name" : "asking",
"value" : "yes"
});
request = $.ajax({
"dataType" : "json",
"type" : "GET",
"url" : sSource,
"data" : aoData,
"success" : fnCallback
});
},
"aoColumns" : [
{
"mDataProp" : "name"
},
{
"mDataProp" : "expr"
},
{
"mDataProp" : "seq"
}
]
});
$('button#bam-btn').on('click', function() {
var anSelected = fnGetSelected( oTable );
oTable.fnDeleteRow( anSelected[0] );
} );
});
I had a similar problem with a table with dynamic data load. Every time I was adding contents, the old nodes disappear, losing the events linked.
I solved the problem invoking a function after the data load:
function insertevents(table_id){
var oTable = jQuery('#'+tableid).dataTable( {"bRetrieve": true });
oTable.$('tr').click(function(){
jQuery(this).toggleClass('row_selected');
} );
// Extra code here
}
It's important to add the "bRetrieve" parameter because the table was previously initialized.
Also, I've improved the functionality controlling keyboard events for accessibility:
oTable.$('tr').keyup( function(event) {
if (event.which == 13 || event.which == 32) {
event.preventDefault();
jQuery(this).toggleClass('row_selected');
}
} );
oTable.$('tr').keydown( function(event) {
if (event.which == 13 || event.which == 32) {
event.preventDefault(); // Desactivamos este efecto
}
});
This bunch of lines should replace the comment line of the first example. Now the table can be used from the keyboard, selecting with intro or space key. Remember to add a tabindex=0 to the elements inserted in the table, so we can navigate with the tab key.
http://editor.datatables.net/release/DataTables/extras/Editor/examples/index.html
This is similar to what you want.
Related
I'm new in Ext, I see some codes in Ext.onReady(...)
tabItems.push({
id : 'schema-${form.schema.id}',
title : '${form.description}',
tabTip : '${form.description}',
tooltipType: 'title',
xtype : 'ttpanel',
executeScripts : true,
listeners : { load : initObjs, unload : unloadObjs, activate : ... },
autoLoad : { url : 'selection.do',
params : ...,
scripts : true,
callback : cb1
}
}
);
My question is, of:
"load:initObjs",
"callback:cb1",
page is rendered and user can operate it,
which of these three runs first? Why?
Thanks a million!
I'm new in jsTree and I have 2 questions.
*Explanation: *
I have jsTree of many hierarchies based on their ids and types and I'm trying to implement load on demand technique. On page load, I display only first hierarchy (root nodes) with no children. Then when I click on any of the node, I go and retrieve the children(in JSON format) of that particular node based on it's id and it's type. jsTree appends the hierarchies successfully on the browser but it fails to acknowledge that the clicked node is a parent of the loaded nodes (Logically I would expect this because I didn't tell jsTree to do so). So, now my questions come:-
1) How do I dynamically make this clicked node as a parent of those loaded nodes?.
2.) I have to double click on the node for jsTree to load the corresponding children. How do I do that in just a single click?
Thanks in advance.
Here is my code code:
In the Servlet, I have the following conditional statements:-
if(type.equals("root"))
{
String jsonString = TreeTest.getRoot().getString("data");
out.write(jsonString);
}
else if(type.equals("rig"))
{
String jsonString = TreeTest.getSecondHierarchy(Integer.parseInt(id)).getString("data");
out.write(jsonString);
}
else if(type.equals("well"))
{
String jsonString = TreeTest.getThirdHierarchy(Integer.parseInt(id)).getString("data");
out.write(jsonString);
}
The JSONObject which I am returning for every call is in the form of
"data": {
"data" : "node_name",
"attr": {"id": node_id, "type" : "node_type"}
}
Here is my jsTree codes
$(document).ready(function(){
$("#tree").jstree({
"themes": {"theme": "classic"},
"core" : {
"strings" : {
"loading" : "Loading data..."
}
},
"json_data": {
"ajax" : {
"type": 'GET',
"url": "TreeViewServlet",
"data": function(n)
{
return{
"id" : n.attr ? n.attr("id") : 0,
"type": n.attr? n.attr("type"): "root"
};
}
}
},
"types" : {
"types" : {
"rig" : {
"icon" : {
"image" : "./images/Rig.gif"
}
},
"well" : {
"icon" : {
"image" : "./images/Well.gif"
}
},
"assysystype" : {
"icon" : {
"image" : "./images/whxt.gif"
}
},
"assy" : {
"icon" : {
"image" : "./images/Assy.gif"
}
},
"_Drl-WH" : {
"icon" : {
"image" : "./images/w_icon.gif"
}
},
"_Compl-XT" : {
"icon" : {
"image" : "./images/x_icon.gif"
}
},
"subAssy" : {
"icon" : {
"image" : "./images/subass.gif"
}
}
}
},
"plugins" : ["themes","json_data","ui", "core", "types"]
}).delegate(".jstree-open>a", "click.jstree", function(event)
{
$.jstree._reference(this).close_node(this,false,false);
}).delegate(".jstree-closed>a", "click.jstree", function(event)
{
$.jstree._reference(this).open_node(this,false,false);
});
});
I solved my own question and decided to post an answer:-
1) I had to get the ID of clicked node and send it to the Java Servlet, the Servlet then processes the request and returns a JSON string of all children of this node and then using AJAX, I append the children back to the tree.
2) There was a magic key, for every node, I added "state" : "closed" and that was it.
how to set_type when loading jstree? I need disable some node after load jstree, and before use it. I defined a new type "disabled", but I dont know how to use it. I have found many solutions and read docs. I still confused. How to set type to the node? why does this not work in my code to call set_type? My source is html_data. can anyone give me some references or advices? thx
$("#demo1").jstree({
"checkbox" : {"two_state" : true},
"plugins" : [ "themes", "html_data", "checkbox", "ui" ],
"types" : {
"types": {
"disabled" : {
"check_node" : false,
"uncheck_node" : false,
// "select_node" : function () {return false;}
}
}
}
});
$("#demo1").bind("loaded.jstree", function (e, data) {
$.jstree._reference("#demo1").get_unchecked(0, true).each(function(){
if($(this).children().length <= 2){
if("-1" == this.title ) {
$(this).jstree("set_type", "disabled");
$.jstree._reference("#demo1").set_type("disabled", "#-1");
}
}
});
I would like to display a fancybox when a user clicks the Create button to have them fill in a form. This is used to capture additional data and associate it with the newly created node in jsTree. I need to get the ID of the newly created node and pass it along as a GET parameter in the fancybox call. So far I just can't seem to figure out how to get the ID.
Here is what I have so far:
$("#demo").jstree({
// List of active plugins
"plugins" : ["themes", "json_data", "ui", "crrm", "cookies", "dnd", "search", "types", "hotkeys", "contextmenu", "unique"],
.bind("create.jstree", function (e, data) {
$.post(
"server.php",
{
"operation" : "create_node",
"id" : data.rslt.parent.attr("id").replace("node_",""),
"position" : data.rslt.position,
"title" : data.rslt.name,
"type" : data.rslt.obj.attr("rel")
},
function (r) {
if(r.status) {
$(data.rslt.obj).attr("id", "node_" + r.id);
}else{
$.jstree.rollback(data.rlbk);
}
}
);
})
$("#demo").bind("before.jstree", function (e, data) {
if(data.func === "create") {
var id = data.args[0].attr("id").replace("node_","");
showFancybox("edit_task.php?action=create&parent_id="+id);
}
})
// Code for the menu buttons
$(function () {
$("#mmenu input").click(function () {
switch(this.id) {
case "add_default":
case "add_folder":
$("#demo").jstree("create", null, "last", { "attr" : { "rel" : this.id.toString().replace("add_", "") } });
break;
case "search":
$("#demo").jstree("search", document.getElementById("search_text").value);
break;
case "text": break;
default:
$("#demo").jstree(this.id);
break;
}
});
});
The code that I have now finds the parent id before the new node is created. I tried waiting a few seconds and then trying to read the newest entry from the database, but this doesn't work very reliably and is slower than needed. How can I get the new node's ID from jsTree once it's been created and added to the database?
This works:
id = data.args[0].attr("id");
Right now, the server response I'm working with sends back a JSON response like this:
{"status":1}
After saving, jeditable places the actual response: {"status":1} on the page. Anyway to get around this issue?
A better solution is to post-process the returned json data before it hits the page.
Suppose your server returns the following json string:
{ "status": 1, "result": "value to be displayed", "other": "some other data" }
and you would like to process the "status" and "other" fields, and display the "result" field in the jeditable input field.
Add the following 2 lines to jquery.jeditable.js:
(around line 95):
var intercept = settings.intercept || function(s) {return s; };
(around line 350, right after " success : function(result, status) {"
result = intercept.apply(self,[result]);
Then, in your own code, do something like the following:
$(some_field).editable(
'/some_url_on_your_server',
{
indicator : "<img src='/images/spinner.gif'>",
tooltip: "Click to edit.",
indicator: "Saving...",
onblur: "submit",
intercept: function (jsondata) {
obj = jQuery.parseJSON(jsondata);
// do something with obj.status and obj.other
return(obj.result);
},
etc.
This allows you do cool stuff like having your server convert abbreviations to full strings etc.
Enjoy!
There's a simple way of doing this by using the callback. .editable() converts any response to a string, so the response has to be converted to a JSON variable. The values can then be retrieved and then written using a '.text()' method. Check the code:
$("#myField").editable("http://www.example.com/save.php", {
submit : 'Save',
cancel : 'Cancel',
onblur : "ignore",
name : "sentText",
callback : function(value, settings) {
var json = $.parseJSON(value);
$("#myField").text(json.sentText);
}
});
This is how I handled the json response.
First, set the datatype using ajaxoptions. Then, handle your data in the callback function. Therein, this.revert is your original value.
oTable.$('td:eq(3)').editable('/admin/products/add_quantity_used', {
"callback" : function(sValue, y) {
var aPos = oTable.fnGetPosition(this);
if($("#dialog-message").length != 0){
$("#dialog-message").remove();
}
if(!sValue.status){
$("body").append('<div id="dialog-message" style="display:none;">'+sValue.value+'</div>');
$( "#dialog-message" ).dialog({
modal: true,
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
});
if(this.revert != '')
oTable.fnUpdate(this.revert, aPos[0], aPos[1]);
else
oTable.fnUpdate("click to edit", aPos[0], aPos[1]);
}else
if(sValue.status)
oTable.fnUpdate(sValue.value, aPos[0], aPos[1]);
},
"submitdata" : function(value, settings) {
return {
"data[users_to_products][users_to_products_id]" : this.parentNode.getAttribute('id'),
"column" : oTable.fnGetPosition(this)[2]
};
},
"height" : "30px",
"width" : "30px",
"maxlength" : "3",
"name" : "data[users_to_products][quantity_used]",
"ajaxoptions": {"dataType":"json"}
}).attr('align', 'center');
So the solution I came up with is similar to what madcapnmckay answered here.
var editableTextArea = $('.editable-textarea');
editableTextArea.editable(submitEditableTextArea, {
type : 'textarea',
cancel : 'Cancel',
submit : 'Save',
name : editableTextArea.attr('id'),
method : 'post',
data : function(value, settings) {
return $.fn.stripHTMLforAJAX(value);
},
event : "dblclick",
onsubmit : function(value, settings) {
//jquery bug: on callback reset display from block to inline
$('.btn-edit').show(0, function(){$(this).css('display','inline');});
},
onreset : function(value, settings) {
//jquery bug: on callback reset display from block to inline
$('.btn-edit').show(0, function(){$(this).css('display','inline');});
}
});
Then the url function is
function submitEditableTextArea(value, settings) {
var edits = new Object();
var result = $.fn.addHTMLfromAJAX(value);
edits[settings.name] = [value];
var returned = $.ajax({
type : "POST",
data : edits,
dataType : "json",
success : function(_data) {
var json = eval( _data );
if ( json.status == 1 ) {
console.log('success');
}
}
});
return(result);
}