Giving a simple table like this
<table id="exampleTable" class="table hover nowrap">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead></table>
Also, using the jQuery Datatable plugin and making the rows selectable, like in this example. The Javascript goes like this:
var exampleTable = $("#exampleTable").DataTable(
{
"bDestroy": true,
"lengthChange": false,
"bPaginate": false
});
$('#exampleTable tbody').on( 'click', 'tr', function () {
if ( $(this).hasClass('selected') ) {
$(this).removeClass('selected');
}
else {
$('#exampleTable tr.selected').removeClass('selected');
$(this).addClass('selected');
}
} );
So, when the table is empty, it shows a selectable row which says something like:
No data available in table
How to detect the table is empty and not allow selection on that kind of "message rows"?
Here is a fiddle with the code.
you can check if there is td with the class dataTables_empty like this:
$('#exampleTable tbody').on( 'click', 'tr', function () {
if ( $(this).hasClass('selected')) {
$(this).removeClass('selected');
}
else if(! $(this).find('td.dataTables_empty').length){
$('#exampleTable').DataTable().rows().nodes().each(function(){
$(this).removeClass('selected');
});
$(this).addClass('selected');
}
} );
You can use the - .row().data() method to see if there is data. if this returns undefined, you can disable selection of the row.
i also think this would be an ideal solution instead of dom traversal which is more expensive. what do you guys think ?
below is the updated fiddle. you can comment the tbody from the html to test it.
Let me know if this helps.
Modified Fiddle
inside your click method, add before everything
if($('#exampleTable tbody tr td').length == 1){
return;
}
Anyway, I got this button that is supposed to open my nav.
HAML:
%button#nav-toggle{ :navigate => 'false' } Menu
HTML:
<button id='nav-toggle' navigate='false'>Menu</button>
And I'm binding two clicks on it like this:
jQuery
$(document).ready(function(){
$("#nav-toggle[navigate='false']").click(function(){
console.log("opening nav");
$("#nav-toggle").attr('navigate','true');
$( "#masthead" ).animate({
height:'100vh',
}, {
duration: 1000,
queue: false,
done: function() {
console.log("first done");
}
}
);
});
$("#nav-toggle[navigate='true']").click(function(){
console.log("closing nav");
$("#nav-toggle").attr('navigate','false');
$( "#masthead" ).animate({
height:'10vh',
}, {
duration: 1000,
queue: false,
done: function() {
console.log("second done");
}
}
);
});
});
For some reason, when I click the button for the second time (When its navigate-attribute is set to true, it still launches the first event of those two.
What am I missing here?
Full code here: Codepen
You need to delegate the event.
Take a look at this
http://codepen.io/anon/pen/jAjkpA?editors=1010
You need to bind the event to a parent in this case the .hamb-container.
Here's a link to understand how delegation and event bubbling works https://learn.jquery.com/events/event-delegation/.
Basically as a summary:
When an event is triggered it bubbles the event all the way up to your root HTML tag.
That is good for when you want to add dynamic content or in your case pick out an attribute that changes dynamically.
So how do we bind to dynamic content? Simple. We surround them with a static container and bind to that instead. Additionally, we let JQuery know what the dynamic content will be. So Jquery will listen for an event on the static element and check if it actually originated from the element you were looking for.
Something like this
$( "#staticAncestor" ).on( "click", "#DynamicContent", function( event ) {
});
Hope this helps. Happy coding!
For some reason, when I click the button for the second time (When its navigate-attribute is set to true, it still launches the first event of those two.
What am I missing here guys and girls?
You missed nothing.
An event is bound to an element not to a property/attribute.
Because .click a shortcut for .on( "click", handler ):
.on( events [, selector ] [, data ], handler ): Attach an event handler function for one or more events to the selected elements
So, you can change your code like:
$(function () {
$("#nav-toggle[navigate='false']").click(function(){
console.log("opening nav");
var attr= ($("#nav-toggle").attr('navigate') == 'false' ? false : true);
$("#nav-toggle").attr('navigate',!attr);
if (!attr) {
$( "#masthead" ).animate({
height:'100vh',
}, {
duration: 1000,
queue: false,
done: function() {
console.log("first done");
}
}
);
} else {
$( "#masthead" ).animate({
height:'10vh',
}, {
duration: 1000,
queue: false,
done: function() {
console.log("second done");
}
}
);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<button id='nav-toggle' navigate='false'>Menu</button>
I am implementing datatbales and according to my requirement, most of the things have been resolved except the pagination issue. In my case for every time pagination navigation is displaying. I want to disable the pagination navigation if there is only one page at all.How to do that? My code is like:
JS
<script>
function fnFilterColumn(i) {
$('#example').dataTable().fnFilter(
$("#col" + (i + 1) + "_filter").val(),
i
);
}
$(document).ready(function() {
$('#example').dataTable({
"bProcessing": true,
"sAjaxSource": "datatable-interestdb.php",
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"sDom": 'T<"clear">lfrtip',
"oTableTools": {
"aButtons": [
{
"sExtends": "csv",
"sButtonText": "Save to CSV"
}
]
},
"oLanguage": {
"sSearch": "Search all columns:"
}
});
$("#example").dataTable().columnFilter({
aoColumns: [
null,
null,
null,
null
]
});
$("#col1_filter").keyup(function() {
fnFilterColumn(0);
});
});
</script>
HTML
<table cellpadding="3" cellspacing="0" border="0" class="display userTable" aria-describedby="example_info">
<tbody>
<tr id="filter_col1">
<td>Interest:</td>
<td>
<input type="text" name="col1_filter" id="col1_filter">
</td>
</tr>
</tbody>
</table>
<table width="100%" border="0" align="center" cellpadding="2" cellspacing="1" class="form_table display" id="example">
<thead>
<tr>
<th class="sorting_asc" width="25%">Interest</th>
<th width="25%">Name</th>
<th width="25%">Email</th>
<th width="25%">Contact No</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4" class="dataTables_empty">Loading data from server</td>
</tr>
</tbody>
<tfoot>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</tfoot>
</table>
Building off of Nicola's answer, you can use the fnDrawCallback() callback and the oSettings object to hide the table pagination after it's been drawn. With oSettings, you don't need to know anything about the table settings (records per page, selectors specific to the table, etc.)
The following checks to see if the per-page display length is greater than the total records and hides the pagination if it is:
$('#your_table_selector').dataTable({
"fnDrawCallback": function(oSettings) {
if (oSettings._iDisplayLength > oSettings.fnRecordsDisplay()) {
$(oSettings.nTableWrapper).find('.dataTables_paginate').hide();
} else {
$(oSettings.nTableWrapper).find('.dataTables_paginate').show();
}
}
});
Documentation
fnDrawCallback()
oSettings
You must hide them dynamically I think, you can use fnDrawCallback()
$('#example').dataTable({
"fnDrawCallback": function(oSettings) {
if ($('#example tr').length < 11) {
$('.dataTables_paginate').hide();
}
}
});
EDIT - another way found here could be
"fnDrawCallback":function(){
if ( $('#example_paginate span span.paginate_button').size()) {
$('#example_paginate')[0].style.display = "block";
} else {
$('#example_paginate')[0].style.display = "none";
}
}
This is the correct approach when working in V1.10+ of JQuery Datatables. The process is generally the same as in previous versions but the event names and API methods are slightly different:
$(table_selector).dataTable({
preDrawCallback: function (settings) {
var api = new $.fn.dataTable.Api(settings);
var pagination = $(this)
.closest('.dataTables_wrapper')
.find('.dataTables_paginate');
pagination.toggle(api.page.info().pages > 1);
}
});
Documentation
https://datatables.net/reference/option/preDrawCallback
https://datatables.net/reference/api/page.info()
See my feature plugin conditionalPaging.
Usage:
$('#myTable').DataTable({
conditionalPaging: true
});
or
$('#myTable').DataTable({
conditionalPaging: {
style: 'fade',
speed: 500 // optional
}
});
Add this code to your datatables initialisation request.
JQUERY
Apply to single datatable:
"fnDrawCallback": function (oSettings) {
var pgr = $(oSettings.nTableWrapper).find('.dataTables_paginate')
if (oSettings._iDisplayLength > oSettings.fnRecordsDisplay()) {
pgr.hide();
} else {
pgr.show()
}
}
Apply to all datatables:
"fnDrawCallback": null
Edit datatables.js to apply the code site wide.
I'm doing following to achieve this goal, as it is more dynamic solution that is not expressed above. as first it is getting total number of pages and then decide to show/hide pagination.
Beauty of this code is only if user change page length then it will not effected.
jQuery('#example').DataTable({
fnDrawCallback: function(oSettings) {
var totalPages = this.api().page.info().pages;
if(totalPages == 1){
jQuery('.dataTables_paginate').hide();
}
else {
jQuery('.dataTables_paginate').show();
}
}
});
jQuery
- I tried with the following options, it worked for me
$("#your_tbl_selector").dataTable({
"pageLength": 3,
"autoWidth": false,
"fixedHeader": {"header": false, "footer": false},
"columnDefs": [{ "width": "100%", "targets": 0 }],
"bPaginate": true,
"bLengthChange": false,
"bFilter": true,
"bInfo": false,
"bAutoWidth": false,
"oLanguage": {
"oPaginate": {
"sNext": "",
"sPrevious": ""
}
},
"fnDrawCallback": function(oSettings) {
if (oSettings._iDisplayLength >= oSettings.fnRecordsDisplay()) {
$(oSettings.nTableWrapper).find('.dataTables_paginate').hide();
}
}
});
DataTable Output View
I prefer #sina's solution. Good job.
But my one comes with some neccessary improvements.
#sina forgot the else part to show the pagination again if neccesary. And I added the possibility to define the all option in the lengthMenu like following:
jQuery('#your_table_selector').dataTable({
"lengthMenu": [[10, 25, 50, 100, 250, 500, -1], [10, 25, 50, 100, 250, 500, "All"]],
"fnDrawCallback": function(oSettings) {
if (oSettings._iDisplayLength == -1
|| oSettings._iDisplayLength > oSettings.fnRecordsDisplay())
{
jQuery(oSettings.nTableWrapper).find('.dataTables_paginate').hide();
} else {
jQuery(oSettings.nTableWrapper).find('.dataTables_paginate').show();
}
}
});
This callback function works generically with any datatable without having to hardcode the table ID:
$('.data-table').dataTable({
fnDrawCallback: function(oSettings) {
if(oSettings.aoData.length <= oSettings._iDisplayLength){
$(oSettings.nTableWrapper).find('.dataTables_paginate').hide();
}
}
});
Just add the following to your stylesheet:
.dataTables_paginate .paginate_button.disabled {
display: none;
}
I know this is an old post but for those of us that will be using this, and have OCD just like me, a change is needed.
Change the if statement,
if (oSettings._iDisplayLength > oSettings.fnRecordsDisplay())
to
if (oSettings._iDisplayLength >= oSettings.fnRecordsDisplay())
With this little change you will see the pagination buttons for records lengths greater than 10, 25, 50, 100 instead of presenting the pagination buttons with only 10 records, technically 10, 25, etc records is still a one page view.
You can follow this way also.
"fnDrawCallback":function(){
if(jQuery('table#table_id td').hasClass('dataTables_empty')){
jQuery('div.dataTables_paginate.paging_full_numbers').hide();
} else {
jQuery('div.dataTables_paginate.paging_full_numbers').show();
}
}
This worked for me.
I tried to make sPaginationType as Dynamic in datatable for every entry but i can't find proper solution for that but what i did was
"fnDrawCallback": function(oSettings) {
$('select[name="usertable_length"]').on('change', function(e) {
var valueSelected = this.value;
if ( valueSelected < 10 ) {
$('.dataTables_paginate').hide();
} else {
$('.dataTables_paginate').show();
}
});
},
$('#dataTable_ListeUser').DataTable( {
//usual pager parameters//
"drawCallback": function ( settings ) {
/*show pager if only necessary
console.log(this.fnSettings());*/
if (Math.ceil((this.fnSettings().fnRecordsDisplay()) / this.fnSettings()._iDisplayLength) > 1) {
$('#dataTable_ListeUser_paginate').css("display", "block");
} else {
$('#dataTable_ListeUser_paginate').css("display", "none");
}
}
});
This isn't directly possible as DataTables doesn't support enabling and disabling features are run time. However, what you could do is make use of the fnDrawCallback() function to check to see if there is only one page, and if so hide the pagination controls.
If your data is not dynamic, i.e., server generates HTML table which is then enhanced by DataTables you can render the paging option on the server (I am using razor).
$("#results").dataTable({
paging: #(Model.ResultCount > Model.PageSize ? "true" : "false"),
// more ...
});
Here is my solution, it works also if you have multiple tables on the same page. It prevents the colision for example (table A must have pagination, and B must not).
tableId in my code is never undefined. If you haven't defined an ID for your table, dataTable will do it for you by adding something like 'DataTables_Table_0'
fnDrawCallback: function (oSettings) {
if ($(this).DataTable().column(0).data().length <= oSettings._iDisplayLength) {
var tableId = $(this).attr('id');
$('#' + tableId + '_paginate').hide();
}
}
This Solved my issues:
.dataTables_paginate .disabled {
display:none;
}
dataTables_paginate .disabled + span {
display:none;
}
Hope it helps you all
$("#datatable").DataTable({
"fnDrawCallback": function (oSettings) {
if ($(oSettings.nTBody).find("tr").length < $(oSettings.nTableWrapper).find("select[name=fileList_length]").val()) {
$(oSettings.nTableWrapper).children(".dataTables_paginate").hide();
}
}
});
this worked for me:
if ($('#dataTableId_paginate').find('li').length < 4) {
$('#segment-list_paginate').html('');
}
I have an Accordion function like this:
$("#notaccordion").addClass("ui-accordion ui-widget ui-helper-reset")
.find("h3")
.addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom")
.prepend('<span class="ui-icon ui-icon-triangle-1-e"/>')
.click(function () {
$(this).toggleClass("ui-accordion-header-active").toggleClass("ui-state-active")
.toggleClass("ui-state-default").toggleClass("ui-corner-bottom")
.find("> .ui-icon").toggleClass("ui-icon-triangle-1-e").toggleClass("ui-icon-triangle-1-s");
if ($(this).next().is(':hidden') == true) {
;
$(this).addClass('active'); $(this).next().slideDown('normal');
}
else {
$(this).removeClass('active'); $(this).next().slideUp('normal');
}
//.end().next().slideUp('normal');
return false;
})
.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide();
and a click all panels function to expand all panels at once:
function clickAllPanels() {
var elm = document.getElementsByTagName('table');
var i = elm.length; while (i--) {
clickItem(elm[i]);
}
}
function clickItem(divObj) {
if (divObj.click) {
divObj.click();
} else if (document.createEvent) {
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
var allowDefault = divObj.dispatchEvent(evt);
}
}
How can I let the accordion .click(function () function know that it's clickAllPanels that is sending the 'clicks' instead of a user's physical click. I need to do this because I want to change the slide up and down logic if it's from clickAllPanels.
The way I'd do it is to use two different event names, one being "click" and the other being something like "forced-click":
$( ... whatever ... ).bind("click forced-click", function(ev) {
if (ev.type === "forced-click") {
// called by programmatic trigger
}
// ...
});
When you trigger the event:
$( ... whatever ... ).trigger("forced-click");
Another way to do it I guess would be to check the event object to see if there's an "originalEvent" property. If not, then you know it was triggered programmatically. Personally I don't like to rely on that because it's not documented.
It is often a good idea to have separate functions for the event handler and for the actual work you are doing:
function do_stuff(suitable_arguments, a_flag){
//...
}
$(/*...*/).click(function(){
do_stuff( /*...*/, true);
}
in_my_other_code(){
do_stuff( /*...*/, false);
}
By detaching your logic from the event handling you have much more flexibility in choosing when and how to invoke it.
Why don't you use jquery in your 'clickItem()' function:
function clickItem(divObj) {
$(divObj).trigger('click', { manual: true });
}
The event parameter in you click handler will have a property "isTrigger", which won't exist when items are clicked with the mouse:
$("#notaccordion")
...
.click(function(e) {
if (e['isTrigger']) {
// do this
} else {
// do that
}
});
Here's a fiddle
I am trying to insert buttons into the JQuery DataTables but it seems that when the button is pressed, nothing happen.
The code as follows (for the JQuery Datatable):
var oTable = $('#example').dataTable( {
"aaData": movieclips,
"bProcessing": true,
"bAutoWidth": false,
"fnInitComplete": function() {
var oSettings = this.fnSettings();
for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ ){
if(oSettings.aoPreSearchCols[i].sSearch.length>0){
$("tfoot input")[i].value = oSettings.aoPreSearchCols[i].sSearch;
$("tfoot input")[i].className = "";
}
}
},
"aoColumns": [
{
"sTitle": "Title",
"sClass": "center",
"sWidth": "80%"
},
{
"sTitle": "Video URL",
"sClass": "center",
"fnRender": function(obj) {
var sReturn = obj.aData[ obj.iDataColumn ];
var returnButton = "<input class='approveButton' type='button' name='" + sReturn + "' value='Play'></input>";
return returnButton;
},
"sWidth": "20%"
}
]
} );
The approveButton function as follows:
$(".approveButton").click(function() {
alert(this.name);
try {
alert(this.name);
} finally {
return false;
}
}
Any Insight?
If you assign the handler with $(".approveButton").click(...) it will only apply to elements that already exist which match the ".approveButton" selector at that moment. That is, elements created later will not automatically get handlers of their own. I'm assuming that that is the problem - if not you can disregard the following...
Fortunately there is a mechanism for creating a handler that will automatically work on matching elements that are created in the future:
$(document).on("click", ".approveButton", function() {
// your function code here
});
Notice that the initial selector is document - this will work, but you should set it up on a parent element closer to your buttons if you can, so perhaps the following:
$("#example").on("click", ".approveButton", function() { /* your code */ });
(I'm not sure if "#example" is the most appropriate parent for this purpose, but you don't show any of your HTML, so...)
Have a look at the jQuery doco for .on() for more information.
Or, if you're using a version of jQuery older than 1.7 you can use `.delegate()'
If you use jquery < 1.7 you should use delegate() or live()
$(".approveButton").live('click', function() {
alert(this.name);
try {
alert(this.name);
} finally {
return false;
}
}
$("body").delegate(".approveButton", "click", function() {
alert(this.name);
try {
alert(this.name);
} finally {
return false;
}
}
otherwise use on() as suggested by nnnnnn