Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with adding hint text in Jquery data table search box

Using a plugin such as watermark.js for adding the greyed out hint text in the search field of the Jquery datatable is not an option, I have to custom write it. I am almost there but facing this minor and strange issue explained below the following code snippet.

function toggleHintText()
{
    // alert("The hint text should show up"); 
    var textSuggest = "Please input search parameter";
    var searchField = $('input:text');

    searchField .attr("value", textSuggest );
    searchField .addClass("activeHint");

    searchField .focus(function() {
    if(searchField .attr("value") == textSuggest)
    {
        searchField .attr("value", "");
    }
    });

    searchField .keyup(function() {             
    if(searchField .attr("value") == "") 
    {
      searchField .addClass("activeHint");
    }
    else
    {
      searchField .removeClass("activeHint");   
    }
    });     

    searchField .blur(function() {
    if(searchField .attr("value") == "")
    {
        searchField .attr("value", hinttext);
        searchField .addClass("activeHint");
    }
    });   

}

This method is called onload as below

$(document).ready(function() {
populateTableData();
toggleHintText();
} );

===========================================================================================

The issue I am facing is that without the alert that I have in the beginning of the method, the hint text doesn't show up in the search box. Does the alert some how work in favor of document.ready ? Does calling two methods from document.ready mess up the toggleHint method ?. One of my requirements is to preserve the user input search text if he clicks on the table row after search query and then hits the a custom back button, that is why I have to call it from document.ready.

Please advise and thanks in advance.

like image 458
user1006072 Avatar asked Dec 05 '11 03:12

user1006072


2 Answers

Try utilizing .queue() , .delay() , .keyup()

$(document).ready(function() {
  var data = $("#example");
  data.DataTable();
  $("input[type=search]")
    .on("keyup", {
      // if input , delay until no input for 1.2 seconds
      "delay": 1200
    }, function(e) {
      var elem = $(this);
      var update = function update() {
        // wait 1.2 seconds to update `val` with "hint"
        if ($.now() - e.timeStamp > e.data.delay 
            && e.target.value.length > 0 && !/^\s/.test(e.target.value)) {
          var val = e.target.value.toLowerCase();
          // filter `.DataTable().data()`
          // return items where first index matches `val`
          var res = $.grep(data.DataTable().data(), function(value, key) {
              return val === value[0].slice(0, val.length).toLowerCase() 
                     || new RegExp(val, "i").test(value[0])
            })
            // sort returned data
            .sort()
            // filter returned data `res` for match to `val`
            .filter(function(hint) {
              return hint[0].toLowerCase().slice(0, val.length) === val 
                     || new RegExp(val, "i").test(hint) 
            })[0];
          elem.val(res[0])
          .css({
            "color": "grey",
            "fontStyle": "italic"
          });
        } else {
          return elem.queue("update", update)
        }
      };
      var defer = function defer(next) {
        // if input before 1.2 seconds ,
        // empty `"update"` queue , delay calling 
        // update until no input for 1.2 seconds
        elem.queue("update", [])
        elem.delay(e.data.delay, "update")
        .queue("update").push(update);
        return next()
      };
      // if input, do stuff
      if (e.target.value.length > 0) {
          elem
          .queue("update", defer)
          .dequeue("update")
      } else {
        elem
        .queue("update", [])
      }
    }).keyup()
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<link href="https://cdn.datatables.net/1.10.7/css/jquery.dataTables.css" rel="stylesheet" />
<script src="https://cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>
<table id="example" class="display" cellspacing="0" width="100%">
  <thead>
    <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Office</th>
      <th>Age</th>
      <th>Start date</th>
      <th>Salary</th>
    </tr>
  </thead>
  <tfoot>
    <tr>
      <th>Name</th>
      <th>Position</th>
      <th>Office</th>
      <th>Age</th>
      <th>Start date</th>
      <th>Salary</th>
    </tr>
  </tfoot>
  <tbody>
    <tr>
      <td>Tiger Nixon</td>
      <td>System Architect</td>
      <td>Edinburgh</td>
      <td>61</td>
      <td>2011/04/25</td>
      <td>$320,800</td>
    </tr>
    <tr>
      <td>Garrett Winters</td>
      <td>Accountant</td>
      <td>Tokyo</td>
      <td>63</td>
      <td>2011/07/25</td>
      <td>$170,750</td>
    </tr>
    <tr>
      <td>Ashton Cox</td>
      <td>Junior Technical Author</td>
      <td>San Francisco</td>
      <td>66</td>
      <td>2009/01/12</td>
      <td>$86,000</td>
    </tr>
    <tr>
      <td>Cedric Kelly</td>
      <td>Senior Javascript Developer</td>
      <td>Edinburgh</td>
      <td>22</td>
      <td>2012/03/29</td>
      <td>$433,060</td>
    </tr>
    <tr>
      <td>Airi Satou</td>
      <td>Accountant</td>
      <td>Tokyo</td>
      <td>33</td>
      <td>2008/11/28</td>
      <td>$162,700</td>
    </tr>
    <tr>
      <td>Brielle Williamson</td>
      <td>Integration Specialist</td>
      <td>New York</td>
      <td>61</td>
      <td>2012/12/02</td>
      <td>$372,000</td>
    </tr>
    <tr>
      <td>Herrod Chandler</td>
      <td>Sales Assistant</td>
      <td>San Francisco</td>
      <td>59</td>
      <td>2012/08/06</td>
      <td>$137,500</td>
    </tr>
    <tr>
      <td>Rhona Davidson</td>
      <td>Integration Specialist</td>
      <td>Tokyo</td>
      <td>55</td>
      <td>2010/10/14</td>
      <td>$327,900</td>
    </tr>
    <tr>
      <td>Colleen Hurst</td>
      <td>Javascript Developer</td>
      <td>San Francisco</td>
      <td>39</td>
      <td>2009/09/15</td>
      <td>$205,500</td>
    </tr>
    <tr>
      <td>Sonya Frost</td>
      <td>Software Engineer</td>
      <td>Edinburgh</td>
      <td>23</td>
      <td>2008/12/13</td>
      <td>$103,600</td>
    </tr>
    <tr>
      <td>Jena Gaines</td>
      <td>Office Manager</td>
      <td>London</td>
      <td>30</td>
      <td>2008/12/19</td>
      <td>$90,560</td>
    </tr>
    <tr>
      <td>Quinn Flynn</td>
      <td>Support Lead</td>
      <td>Edinburgh</td>
      <td>22</td>
      <td>2013/03/03</td>
      <td>$342,000</td>
    </tr>
    <tr>
      <td>Charde Marshall</td>
      <td>Regional Director</td>
      <td>San Francisco</td>
      <td>36</td>
      <td>2008/10/16</td>
      <td>$470,600</td>
    </tr>
    <tr>
      <td>Haley Kennedy</td>
      <td>Senior Marketing Designer</td>
      <td>London</td>
      <td>43</td>
      <td>2012/12/18</td>
      <td>$313,500</td>
    </tr>
    <tr>
      <td>Tatyana Fitzpatrick</td>
      <td>Regional Director</td>
      <td>London</td>
      <td>19</td>
      <td>2010/03/17</td>
      <td>$385,750</td>
    </tr>
    <tr>
      <td>Michael Silva</td>
      <td>Marketing Designer</td>
      <td>London</td>
      <td>66</td>
      <td>2012/11/27</td>
      <td>$198,500</td>
    </tr>
    <tr>
      <td>Paul Byrd</td>
      <td>Chief Financial Officer (CFO)</td>
      <td>New York</td>
      <td>64</td>
      <td>2010/06/09</td>
      <td>$725,000</td>
    </tr>
    <tr>
      <td>Gloria Little</td>
      <td>Systems Administrator</td>
      <td>New York</td>
      <td>59</td>
      <td>2009/04/10</td>
      <td>$237,500</td>
    </tr>
    <tr>
      <td>Bradley Greer</td>
      <td>Software Engineer</td>
      <td>London</td>
      <td>41</td>
      <td>2012/10/13</td>
      <td>$132,000</td>
    </tr>
    <tr>
      <td>Dai Rios</td>
      <td>Personnel Lead</td>
      <td>Edinburgh</td>
      <td>35</td>
      <td>2012/09/26</td>
      <td>$217,500</td>
    </tr>
    <tr>
      <td>Jenette Caldwell</td>
      <td>Development Lead</td>
      <td>New York</td>
      <td>30</td>
      <td>2011/09/03</td>
      <td>$345,000</td>
    </tr>
    <tr>
      <td>Yuri Berry</td>
      <td>Chief Marketing Officer (CMO)</td>
      <td>New York</td>
      <td>40</td>
      <td>2009/06/25</td>
      <td>$675,000</td>
    </tr>
    <tr>
      <td>Caesar Vance</td>
      <td>Pre-Sales Support</td>
      <td>New York</td>
      <td>21</td>
      <td>2011/12/12</td>
      <td>$106,450</td>
    </tr>
    <tr>
      <td>Doris Wilder</td>
      <td>Sales Assistant</td>
      <td>Sidney</td>
      <td>23</td>
      <td>2010/09/20</td>
      <td>$85,600</td>
    </tr>
    <tr>
      <td>Angelica Ramos</td>
      <td>Chief Executive Officer (CEO)</td>
      <td>London</td>
      <td>47</td>
      <td>2009/10/09</td>
      <td>$1,200,000</td>
    </tr>
    <tr>
      <td>Gavin Joyce</td>
      <td>Developer</td>
      <td>Edinburgh</td>
      <td>42</td>
      <td>2010/12/22</td>
      <td>$92,575</td>
    </tr>
    <tr>
      <td>Jennifer Chang</td>
      <td>Regional Director</td>
      <td>Singapore</td>
      <td>28</td>
      <td>2010/11/14</td>
      <td>$357,650</td>
    </tr>
    <tr>
      <td>Brenden Wagner</td>
      <td>Software Engineer</td>
      <td>San Francisco</td>
      <td>28</td>
      <td>2011/06/07</td>
      <td>$206,850</td>
    </tr>
    <tr>
      <td>Fiona Green</td>
      <td>Chief Operating Officer (COO)</td>
      <td>San Francisco</td>
      <td>48</td>
      <td>2010/03/11</td>
      <td>$850,000</td>
    </tr>
    <tr>
      <td>Shou Itou</td>
      <td>Regional Marketing</td>
      <td>Tokyo</td>
      <td>20</td>
      <td>2011/08/14</td>
      <td>$163,000</td>
    </tr>
    <tr>
      <td>Michelle House</td>
      <td>Integration Specialist</td>
      <td>Sidney</td>
      <td>37</td>
      <td>2011/06/02</td>
      <td>$95,400</td>
    </tr>
    <tr>
      <td>Suki Burks</td>
      <td>Developer</td>
      <td>London</td>
      <td>53</td>
      <td>2009/10/22</td>
      <td>$114,500</td>
    </tr>
    <tr>
      <td>Prescott Bartlett</td>
      <td>Technical Author</td>
      <td>London</td>
      <td>27</td>
      <td>2011/05/07</td>
      <td>$145,000</td>
    </tr>
    <tr>
      <td>Gavin Cortez</td>
      <td>Team Leader</td>
      <td>San Francisco</td>
      <td>22</td>
      <td>2008/10/26</td>
      <td>$235,500</td>
    </tr>
    <tr>
      <td>Martena Mccray</td>
      <td>Post-Sales support</td>
      <td>Edinburgh</td>
      <td>46</td>
      <td>2011/03/09</td>
      <td>$324,050</td>
    </tr>
    <tr>
      <td>Unity Butler</td>
      <td>Marketing Designer</td>
      <td>San Francisco</td>
      <td>47</td>
      <td>2009/12/09</td>
      <td>$85,675</td>
    </tr>
    <tr>
      <td>Howard Hatfield</td>
      <td>Office Manager</td>
      <td>San Francisco</td>
      <td>51</td>
      <td>2008/12/16</td>
      <td>$164,500</td>
    </tr>
    <tr>
      <td>Hope Fuentes</td>
      <td>Secretary</td>
      <td>San Francisco</td>
      <td>41</td>
      <td>2010/02/12</td>
      <td>$109,850</td>
    </tr>
    <tr>
      <td>Vivian Harrell</td>
      <td>Financial Controller</td>
      <td>San Francisco</td>
      <td>62</td>
      <td>2009/02/14</td>
      <td>$452,500</td>
    </tr>
    <tr>
      <td>Timothy Mooney</td>
      <td>Office Manager</td>
      <td>London</td>
      <td>37</td>
      <td>2008/12/11</td>
      <td>$136,200</td>
    </tr>
    <tr>
      <td>Jackson Bradshaw</td>
      <td>Director</td>
      <td>New York</td>
      <td>65</td>
      <td>2008/09/26</td>
      <td>$645,750</td>
    </tr>
    <tr>
      <td>Olivia Liang</td>
      <td>Support Engineer</td>
      <td>Singapore</td>
      <td>64</td>
      <td>2011/02/03</td>
      <td>$234,500</td>
    </tr>
    <tr>
      <td>Bruno Nash</td>
      <td>Software Engineer</td>
      <td>London</td>
      <td>38</td>
      <td>2011/05/03</td>
      <td>$163,500</td>
    </tr>
    <tr>
      <td>Sakura Yamamoto</td>
      <td>Support Engineer</td>
      <td>Tokyo</td>
      <td>37</td>
      <td>2009/08/19</td>
      <td>$139,575</td>
    </tr>
    <tr>
      <td>Thor Walton</td>
      <td>Developer</td>
      <td>New York</td>
      <td>61</td>
      <td>2013/08/11</td>
      <td>$98,540</td>
    </tr>
    <tr>
      <td>Finn Camacho</td>
      <td>Support Engineer</td>
      <td>San Francisco</td>
      <td>47</td>
      <td>2009/07/07</td>
      <td>$87,500</td>
    </tr>
    <tr>
      <td>Serge Baldwin</td>
      <td>Data Coordinator</td>
      <td>Singapore</td>
      <td>64</td>
      <td>2012/04/09</td>
      <td>$138,575</td>
    </tr>
    <tr>
      <td>Zenaida Frank</td>
      <td>Software Engineer</td>
      <td>New York</td>
      <td>63</td>
      <td>2010/01/04</td>
      <td>$125,250</td>
    </tr>
    <tr>
      <td>Zorita Serrano</td>
      <td>Software Engineer</td>
      <td>San Francisco</td>
      <td>56</td>
      <td>2012/06/01</td>
      <td>$115,000</td>
    </tr>
    <tr>
      <td>Jennifer Acosta</td>
      <td>Junior Javascript Developer</td>
      <td>Edinburgh</td>
      <td>43</td>
      <td>2013/02/01</td>
      <td>$75,650</td>
    </tr>
    <tr>
      <td>Cara Stevens</td>
      <td>Sales Assistant</td>
      <td>New York</td>
      <td>46</td>
      <td>2011/12/06</td>
      <td>$145,600</td>
    </tr>
    <tr>
      <td>Hermione Butler</td>
      <td>Regional Director</td>
      <td>London</td>
      <td>47</td>
      <td>2011/03/21</td>
      <td>$356,250</td>
    </tr>
    <tr>
      <td>Lael Greer</td>
      <td>Systems Administrator</td>
      <td>London</td>
      <td>21</td>
      <td>2009/02/27</td>
      <td>$103,500</td>
    </tr>
    <tr>
      <td>Jonas Alexander</td>
      <td>Developer</td>
      <td>San Francisco</td>
      <td>30</td>
      <td>2010/07/14</td>
      <td>$86,500</td>
    </tr>
    <tr>
      <td>Shad Decker</td>
      <td>Regional Director</td>
      <td>Edinburgh</td>
      <td>51</td>
      <td>2008/11/13</td>
      <td>$183,000</td>
    </tr>
    <tr>
      <td>Michael Bruce</td>
      <td>Javascript Developer</td>
      <td>Singapore</td>
      <td>29</td>
      <td>2011/06/27</td>
      <td>$183,000</td>
    </tr>
    <tr>
      <td>Donna Snider</td>
      <td>Customer Support</td>
      <td>New York</td>
      <td>27</td>
      <td>2011/01/25</td>
      <td>$112,000</td>
    </tr>
  </tbody>
</table>

jsfiddle http://jsfiddle.net/o98cpxmf/2/

like image 197
guest271314 Avatar answered Oct 05 '22 22:10

guest271314


«Does the alert some how work in favor of document.ready?»

Sure. But not in favor of document.ready but in favor of "dinamically loaded table data.ready".

See your second code snippet:

  • First you call populateTableData(): I figure out to asynchronously read data from probably remote server via Ajax request.

  • And then, you call toggleHintText() to implement your toggle effect over table rows that I figure out that some callback implemented inside populateTableData() WILL append as soon as the Ajax request (or similar asyinchronous operation) finishes.

Javascript is single-threated (which means that your code is executed in a single thread and, hence, free of any concurrency), but not fully free of concurrency because asynchronous operations are attended by other concurrent threads working or waiting for necessary operations to be finished and, then (completion event triggered), pushes a task in the javascript main tasks loop (event handler attached to that element).

The alert() call stops javascript main loop execution, but not concurrent threads attending asynchronous tasks.

This way, it can complete Ajax request operation successfully (even without server timeout failure because of the "alert pause") and trigger the completion event.

...But the callback attached to that event will not be executed until javascript task loop continues.

Your toggleHintText() function is called SURE before your table data is populated and, without the alert() the rest of its code will NOT found any elements in that table (or at least not any new ones populated by populateTableData()).

So there is the reason why, without the alert(), your code doesn't work.

But I'm not sure why it works even with the alert. I figure out your browser could implement the alert stop as some kind of "paused nextTick()" and execute, at least pending event handlers, as soon as possible (but I think that is not strictly correct in javascript specification).

To avoid this problem, need to call toggleHintText() when you are sure that data is populated in the table. That is:

  • Call it from the event handler that populate the data on the (supposed) Ajax request completion.

  • Trigger your own element in that moment and attach toggleHint() as event handler of it.

Or also, you could modify your toggleHintText() event handlers to be attached to the tables itself (or to the whole document) instead of to later dynamically loaded elements and then check for the event target.

That is what the obsolete .live() jquery method did and which nowadays can be achieved simply with .on() and a target selector. For example:

In your code:

var searchField = $('input:text');
...
searchField.focus(function() {...});

...last row is equivalent to:

searchField.on("focus", function(){});

You can replace it (for instance) with:

$("body").on("focus", 'input:text', function(){...});

That way, the event handler is attached directly to document's body and every focus event, it will check if the target matches given selector (no matter if the element were created before the event handler attachment or not).

In summary: you cannot attach event handler to element that not yet exists.

On the other hand, you have some element manipulation like adding classes and attributes. You can't do it before the element creation, but, similarily, you can attach event handler to its "creation" event.

But, unfortunately, this event doesn't actually exist. But there is techniques to implement it over dom change event. See this question about liveQuery plugin.

like image 32
bitifet Avatar answered Oct 05 '22 23:10

bitifet