Alphy
Alphy

Reputation: 331

Check number of elements jQuery

I would like to get the number of textarea elements in a given table cell. Using that I want to add remove functionality to one element at a time if and only if there are more than two, and also be able to undo the removed textarea if I click an 'undo' link. Below is a sample snippet:

<table class="result_table">
    <tr valign="middle" align="center">
        <td style="font-size:13px; " class="tbody_data side">Dissolution</td>
        <td valign="middle" align="center" style="padding: 0px;" class="tbody_data">
            <input type="hidden" value="2" name="tests[]">
            <textarea style="border:none; vertical-align: middle;" class="det_st form-control">UV</textarea>
        </td>
        <td style="padding: 0px;" class="tbody_data">
            <textarea style="border:none;" class="det_st form-control">USP 38 NF 33 Page 4635</textarea>
        </td>
        <td style="padding: 0px;" class="tbody_data">
            <textarea style="border:none;" class="det_st form-control">Acid Stage Not more than 10.0% [n=6]
            </textarea>
            <textarea style="border:none;" class="det_st form-control">Buffer Stage Not Less than 70.0% [n=6]
            </textarea>
        </td>
        <td style="padding: 0px;" class="tbody_data">
            <textarea style="border:none;" class="det_st form-control"> Acid Stage 107.8% (RSD=5.2%; n=6) </textarea>
            <textarea style="border:none;" class="det_st form-control"> Buffer Stage 102.2% (RSD=0.9%; n=6)</textarea>
        </td>
        <td style="padding: 25px;  width:50px;" class="tbody_data side">
            <select style="border:none; margin:15px; width:145px;" class="select" selected="selected">
                <option value="COMPLIES">COMPLIES</option>
                <option value="COMPLIES">COMPLIES</option>
                <option value="DOES NOT COMPLY">DOES NOT COMPLY</option>
            </select>
            <select style="border:none; margin:15px; width:145px;" class="select" selected="selected">
                <option value="COMPLIES">COMPLIES</option>
                <option value="COMPLIES">COMPLIES</option>
                <option value="DOES NOT COMPLY">DOES NOT COMPLY</option>
            </select>
        </td>
    </tr>
</table>
$(document).on('mouseover', '.result_table tr td', function() {
    $('textarea', this).dblclick(function() {
        $(this).remove()
      alert( $(this).length) //gives one even when a cell contains two teatareas
    });
})

Suggestions welcome.

Upvotes: 0

Views: 84

Answers (3)

emerson.marini
emerson.marini

Reputation: 9348

You wanted to count the number of textareas within a td cell, and make it able to remove it when:

  1. There are 2 or more textareas within the td cell.
  2. The user double clicks the textarea.

You also wanted to be able to undo the operation, by putting the previous removed textareas back into the DOM.

You should use .detach() instead of .remove(). This way you can store the removed element for further use (your undo).

Here's the code with comments explaining it - on the markup I've just added a button to make it possible the undo operation:

$(function() {
    // Initialize an array to store all the removed textareas.
    var removedTextAreas = [];    

    $(".result_table tr td").on("mouseover", function() {
        // How many textareas within this cell?
        var numberOfTextAreas = $("textarea", this).length;

        // Handle the double click event.
        handleDblClick(numberOfTextAreas, this);
    });

    $("#undo").on("click", function() {
        // Is there anything removed and not undone?
        if (removedTextAreas.length > 0) {
            // The undo goes from the last to the first in the list.
            // We always re-attach the last one that has been removed.
            var itemPos = removedTextAreas.length - 1;
            var reAttach = removedTextAreas[itemPos];
            var previous = reAttach.previous;
            var next = reAttach.next;

            if (previous.length > 0) {
                // The removed element had a sibling before it,
                // so let's append it back after this sibling.
                reAttach.textarea.appendTo(reAttach.cell);
            }
            else {
                // The removed element had a sibling after it,
                // so let's append it back before this sibling.
                reAttach.textarea.prependTo(reAttach.cell);
            }

            // We now can remove this item from the list of
            // removed textareas.
            removedTextAreas.splice(itemPos);
        }
    });

    // Let's separate concerns by creating a function.
    // This way you can also reduce the code within the caller.
    function handleDblClick(numberOfTextAreas, el) {
        // The target for the double click.
        var target = $("textarea", el);

        // Let's unbind the double click to start with.
        target.off("dblclick");

        // Two or more textareas?
        if (numberOfTextAreas >= 2) {
            target.on("dblclick", function() {
                // Let's store the removed textarea and some details
                // to identify its current parent and siblings.
                removedTextAreas.push({
                    cell: $(this).closest("td"),
                    previous: $(this).prev("textarea"),
                    next: $(this).next("textarea"),
                    textarea: $(this).detach()                    
                });
            });
        }        
    }
});

Demo

Note: You might need to tweak a bit the part where you identify where to re-attach the element, but I'm sure you got the idea.

Upvotes: 1

phreakv6
phreakv6

Reputation: 2165

This should do the trick within that mouseover callback of yours.

var number_of_textareas = $(this).find('textarea').length;

Upvotes: 1

Quentin Roger
Quentin Roger

Reputation: 6538

You can do something like this :

$(document).on('mouseover', '.result_table tr td', function() {
  $('textarea', this).dblclick(function() {
    var self = $(this);
    var nbelement = self.parent('td').find('textarea').length;
    if (nbelement >= 2) {
      self.remove()
    }
  });
})

https://jsfiddle.net/Tintin37/z5x4bsuc/

Upvotes: 1

Related Questions