Show/Hide input inside cells of datatable table

Show/Hide input inside cells of datatable table

Angelj107Angelj107 Posts: 8Questions: 1Answers: 0
edited November 2021 in DataTables

Hi everyone,
I'm facing the following issue.
I have a datatable that gets the data through ajax. It all works perfectly, but, at in the last column of each row, I want to display a button that, when clicked, will show a text input (it will be a $_POST to an external page).

Here is the code for the column I'm "rendering".

   {
              data: null,
              searchable: false,
              sortable: false,
              targets: 6,
              render: function(data, type, row, meta) {
              
                  return '<input type="image" src="images/auction.png" class ="myButton" width="22" height="22" title="Fai un\' offerta" /><input type="text" class="textInput" value="" hidden/>'
              }
            },

Now, I have this script to "show" or "hide" the input text

$(document).ready(function() {

$(".myButton").click(function() {
$(".textInput")
.hide()
.eq($(this).index('.myButton'))
.toggle()


});
$(document).mouseup(function(e) 
{
var container = $(".textInput");
if (!container.is(e.target) && container.has(e.target).length === 0) 
{
    container.hide();
}
});
});

As intendend, the input image is shown, but even if I click it doesn't show anything.
I know that it works because I've tried it here : https://jsfiddle.net/ya2Lw0vz/2/

I'm using <script src="https://code.jquery.com/jquery-3.4.1.js"></script> for loading jquery.

Why is it not working? Am I doing something wrong?
Maybe should I place it in a specific point in my code?

As for now, the structure of my scripts are the following:

  <script src="https://code.jquery.com/jquery-3.4.1.js"></script>

  <script type ="text/javascript" src="//cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
  <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css">

    (function($) {
      $(document).ready(function() {
.... table information here...
]});

$(document).ready(function() {

$(".myButton").click(function() {
$(".textInput")
.hide()
.eq($(this).index('.myButton'))
.toggle()


});
$(document).mouseup(function(e) 
{
var container = $(".textInput");
if (!container.is(e.target) && container.has(e.target).length === 0) 
{
    container.hide();
}
});
});
      })
    })(jQuery);;

Thank you to whoever will try to help me.

Angelo

Answers

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,765

    See if this example of using jQuery delegated events helps. Otherwise please update the test case to show the issue so we can help debug.

    Kevin

  • Angelj107Angelj107 Posts: 8Questions: 1Answers: 0

    Ok maybe I figured it out.
    Basically the ajax code is not letting me define my function.
    By searching online it seems that I need to use the fnPreDrawCallback.
    I did not try with the problem discussed in the first post because I was searching for a work around to the jquery qtip feature that wasn't working (basically I need to open another page in a modal-like way to send a value to my database).
    This modal-like window that opens in the same page where it's called it's working perfectly in the other pages of my site where I use both this qtip function and the datatable but without AJAX call.

    As the AJAX call from datatable seems to cancel my qtip function defined OUTSIDE the definition of the datatable itself, I tried to use (by looking online) the fnPreDrawCallback to define my qtip function.

    At the first try I was happy. It worked PERFECTLY FINE!
    But soon I found another issue.
    Basically, as soon as I change some values and "redraw" my table (I have a range for certain properties, and when I change that value the datatable redraw itself live) I get this error:

    Uncaught TypeError: jQuery(...).qtip is not a function
    ...
    

    So, my function, that at fresh start in my page is working perfectly good, gets lost in the way after the table is redrawn.

    For better understanding I will post now my full datatable function, hoping that someone will find a way to solve this:

    <script type="text/javascript" src="js/jquery.qtip.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
     <script type ="text/javascript" src="//cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
      <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.11.3/css/jquery.dataTables.min.css">
      <script type="text/javascript" src="oldjs/jquery.qtip.js"></script>
    
      <script type="text/javascript">
        (function($) {
          $(document).ready(function() {
    
            var val_range;
    
    
            var age_min = $("#age_min").val();
            var age_max = $("#age_max").val();
            var age_min_maxvalue = document.getElementById("age_min");
            var age_max_minvalue = document.getElementById("age_max");
            $('#age_min').change(function() {   
                     
                age_min = $('#age_min').val();
                age_max_minvalue.setAttribute('min', age_min) ;  
             
                table.draw();}
            );        
            $('#age_max').change(function() {   
              
                age_max = $('#age_max').val();
                age_min_maxvalue.setAttribute('max', age_max) ;      
              table.draw();}
            );
    
            
            
            var table = $('#table_id').DataTable({
              
              "pageLength": 50,
              "bfilter": true,
              "order": [
                [4, "desc"]
              ],
    
              "searching": true,
              "responsive": true,
              "processing": true,
              "serverSide": true,
              "bPaginate": true,
    
              "ajax": {
                "url": "server_side/scripts/server_processing_freeplayers.php",
                "data": function(d) {
                  // Get the slider inputs to send to the server
                  d.val_min = age_min;
                  d.val_max = age_max;
                  d.posizione = posizione;
                  d.user = "<?php echo $varus_playersearch ?>";
                  d.auc = "<?php echo $varauc_playersearch ?>";
                }
              },
    
              fixedHeader: true,
              "fnDrawCallback":function(){
            jQuery('.auction-tip').each(function() {
            jQuery(this).qtip({
                prerender: true,
                content: {
                  text: function(event, api) {
                    jQuery.ajax({
                        url: api.elements.target.attr('href')
                      })
                      .then(function(content) {
    
                        api.set('content.text', content);
                      }, function(xhr, status, error) {
    
                        api.set('content.text', status + ': ' + error);
                      });
    
                    return '<img src="images/load.gif" alt="Loading..."/>';
                  }
                },
                hide: {
                  fixed: true,
                  delay: 300
                },
    
                position: {
                  my: 'right center',
                  at: 'left center',
                  effect: false
                },
    
                style: {
                  classes: 'qtip-bootstrap',
                  width: 325,
                  height: 215
    
                },
    
                show: {
                  event: 'click',
                },
                hide: {
                  event: 'unfocus'
                },
                api: {
                  events: function() {
                    var api = this;
                    $('form', api.elements.content).submit(function(event) {
                      alert('hey');
                      // process it
                      //api.updateContent('new content'); // set the new content
                      return false; // prevent the default response
                    });
                  }
                },
              })
    
              .bind('click', function(event) {
                event.preventDefault();
                return false;
              });
          });
          },
              columnDefs: [
     {
                  data: null,
                  searchable: false,
                  sortable: false,
                  targets: 5,
                  render: function(data, type, row, meta) {
                    return '<a href="https://www.transfermarkt.it/schnellsuche/ergebnis/schnellsuche?query=' + data[0] + '" target="_blank"><img src="images/tm.png" width="23" height="23" alt="" /></a>'
                  }
                },
               {
                  data: null,
                  searchable: false,
                  sortable: false,
                  targets: 6,
                  render: function(data, type, row, meta) {
                    if ((data[8] !== null) || (((<?php echo $row_dataauc['maxlimit']?><=<?php echo $row_countbid['count(f_silentplayer_bid.sf_teamID)']?>)&&(<?php echo $row_dataauc['maxlimit']?> !== 0)))){
                      return '<img src="images/stop.png" width="22" height="22" />'
                    }
                      else { 
                      return '<a class="auction-tip" href="silentauctionbid.php?recordID='+ data[9] +'"><img src="images/auction.png" width="22" height="22" title="Fai un\'offerta" /></a>'
                  }
                },
        
            }
            /*{
                  data: null,
                  searchable: false,
                  sortable: false,
                  targets: 6,
                  render: function(data, type, row, meta) {
                    if ((data[8] !== null) || (((<?php echo $row_dataauc['maxlimit']?><=<?php echo $row_countbid['count(f_silentplayer_bid.sf_teamID)']?>)&&(<?php echo $row_dataauc['maxlimit']?> !== 0)))){
                      return '<img src="images/stop.png" width="22" height="22" />'
                    }
                      else { 
                      return '<input type="image" src="images/auction.png" class ="myButton" width="22" height="22" title="Fai un\'offerta" /><form action="/silentauctionbid.php?recordID='+data[9]+'" method="post"><input type="text" name="amount" class="textInput" value="" hidden/></form>'
                  }
                },
        
            }*/
          ],
          "fnPreDrawCallback":function(){
            jQuery('.auction-tip').each(function() {
            jQuery(this).qtip({
                prerender: true,
                content: {
                  text: function(event, api) {
                    jQuery.ajax({
                        url: api.elements.target.attr('href')
                      })
                      .then(function(content) {
    
                        api.set('content.text', content);
                      }, function(xhr, status, error) {
    
                        api.set('content.text', status + ': ' + error);
                      });
    
                    return '<img src="images/load.gif" alt="Loading..."/>';
                  }
                },
                hide: {
                  fixed: true,
                  delay: 300
                },
    
                position: {
                  my: 'right center',
                  at: 'left center',
                  effect: false
                },
    
                style: {
                  classes: 'qtip-bootstrap',
                  width: 325,
                  height: 215
    
                },
    
                show: {
                  event: 'click',
                },
                hide: {
                  event: 'unfocus'
                },
                api: {
                  events: function() {
                    var api = this;
                    $('form', api.elements.content).submit(function(event) {
                      alert('hey');
                      // process it
                      //api.updateContent('new content'); // set the new content
                      return false; // prevent the default response
                    });
                  }
                },
              })
    
              .bind('click', function(event) {
                event.preventDefault();
                return false;
              });
          });
          }
        });
    
    

    Hoping that someone will help me,
    I thank you all for your time and efforts.

    Angelo

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,765
    edited November 2021

    I've never used qtip. Looks like you are trying to retrieve the qtip text via Ajax. Take a look at this thread. Sound like fetching the text via ajax is not supported by qtip. Maybe you need to rearrange the ajax call used by qtip similar to what bindrid posted.

    Uncaught TypeError: jQuery(...).qtip is not a function

    My guess is this error is caused by the ajax call you have in the text function of the qtip initializer in line 63. Since its an async request and qtip is not waiting for the response to continue initializing the error occurs. Try initializing a qtip element without Datatables and get that to work first. Qtip seems to be no longer maintained.
    See the qtip docs.

    The preDrawCallback is used to clean up events before the draw. Use drawCallback to apply the events. Looks like you are trying to apply the events in both callbacks which won't work. See the docs for more details.

    For us to help debug the code we will actually need to see a running example showing the issue. Please post a link to your page or a test case replicating the issue.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

  • Angelj107Angelj107 Posts: 8Questions: 1Answers: 0

    Hi Kevin,
    thank you for your time.
    making a test case is something I would like to avoid, because it's a lot difficult for me to fully replicate this case.
    But I found a workaround (even though it's really bad and I don't like it).

    As I told in the previous post, as soon as I refresh the page the qtip is working fine.
    But as soon as I redraw the table it stops working.
    And the reason is (as far as I understood) that the qtip.js file is not loaded.
    And the awful solution I found is to fully include the text of the file inside the drawCallback function.
    So at each draw I know that the qtip functions are loaded.
    And it works now.
    But I don't like as a solution, first of all because I would like to keep my code... smaller :smiley:
    Is there maybe a way to include a js file inside the drawCallback function without copying and pasting the whole js code in it?

    Thank you.

  • kthorngrenkthorngren Posts: 20,277Questions: 26Answers: 4,765

    But as soon as I redraw the table it stops working.
    And the reason is (as far as I understood) that the qtip.js file is not loaded.

    Hos are you redrawing the table?

    And the awful solution I found is to fully include the text of the file inside the drawCallback function.

    There is something wrong with your page if you need to include the text of qtip.js inside the drawCallback function. This would insert a duplicate qtip.js instance each time drawCallback is executed. In order to help we will need to see the page so we can see exactly what you have.

    I took Bindrid's example code and put it into this test case:
    http://live.datatables.net/xefewuto/1/edit

    NOTE: The mouseover ajax function call returns all the data. It is expected that only one row of data, pertaining to the mouseover row, is returned in production.

    The example doesn't use drawCallback. It relies on jQuery Delegated event to create a single event for all elements that contain the classname details.

    Looks like fine tuning of the qtip tool can be made as it can sometimes leave artifacts in the test case. Will leave this part to you as its qtip that needs to remove the old display info.

    Feel free to update my test case to show any Datatables related issues.

    Kevin

Sign In or Register to comment.