splunk
splunk

Reputation: 6779

change ids and classes of html text with jquery on element click

This is my situation:

<div id="div1" class="divPhase">
    <div class="row margin-top-1">
        <div class="column">
            <label>Title Phase 1:</label>
            <textarea id="title-1" name="title-phase-1" rows="6" required></textarea>
        </div>
        <div class="column">
            <label>Description Phase 1:</label>
            <textarea id="description-1" name="description-phase-1" rows="6" required></textarea>
        </div>
        <a class="removeLink">Remove div1</a>
    </div>
</div>
<div id="div2" class="divPhase">
    <div class="row margin-top-2">
        <div class="column">
            <label>Title Phase 2:</label>
            <textarea id="title-2" name="title-phase-2" rows="6" required></textarea>
        </div>
        <div class="column">
            <label>Description Phase 2:</label>
            <textarea id="description-2" name="description-phase-2" rows="6" required></textarea>
        </div>
        <a class="removeLink">Remove div2</a>
    </div>
</div>
....
....
and so on with div3, div4 etc.

As you can see, for each div (div1, div2, div3, and so on) I have a link which will remove its parent div with class divPhase.

Here is the code:

$(".removeLink").closest(".divPhase").remove();

What I'm trying to achieve is to have an ascending ordered and contiguous list of divs even after removing some divs.

I'll try to be more clear. As of now if I have, let's say, 5 divs as the ones above (with these ids: div1, div2, div3, div4 and div5) if I remove div3 with the click on the link with class removeLink what I get is a list of 4 divs (div1, div2, div4 and div5).

This list is not contiguous because between div2 and div4 we need div3. What I'd like to get is div1, div2, div3, div4 (div4 should become div3 and div5 should become).

Moreover I should achieve the same for the textarea's ids (title-5 and description-5 should become title-4 and description-4 while title-4 and description-4 should become title-3 and description-3).

How do I go about this?

Upvotes: 0

Views: 109

Answers (2)

webketje
webketje

Reputation: 10976

Here's a more elegant way to do it: trigger an event when the .divPhase is removed (remove-row), and attach an updateIndexes listener to it. In the body of this function you can change any attributes you like in a loop of all .divPhase's.

Note: although the below snippet works for this use case, if you find yourself often needing to add extra modifications per element/ attribute, you might want to consider a data-first/ template rendering solution, like Handlebars or Mustache, for a comprehensive list see javascripting.com

var removeEntry = function() {
  $('#rows').trigger('remove-row', [$(this).closest('.row').index()]);
  $(this).closest('.row').remove();
};

var updateIndexes = function(e, index) {
  var selector = ':input, .divPhase';
  $('#rows').children().filter(function(i) {
    return i > index;
  }).each(function(i) {
    $(this).find(selector).add(this).each(function() {
      var displayIndex = (i + 1);
      if (this.className && this.className.length)
        this.className = this.className.slice(0, -1) + displayIndex;
      if (this.id && this.id.length)
        this.id = this.id.slice(0, -1) + displayIndex;
      if (this.name && this.name.length)
        this.name = this.name.slice(0, -1) + displayIndex;
      if (this.value && this.value.length)
        this.value = this.value.slice(0, -1) + displayIndex;
    });
  });
};

$('#rows').on('remove-row', updateIndexes);
$('.row a').on('click', removeEntry);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="rows">
  <div class="row divPhase-1">
    <input type="text" name="title-1" id="title-1" value="value-1">
    <textarea name="desc-1" id="desc-1"></textarea>
    <a href="#desc-1-removed">Remove</a>
  </div>
  <div class="row divPhase-2">
    <input type="text" name="title-2" id="title-2" value="value-2">
    <textarea name="desc-2" id="desc-2"></textarea>
    <a href="#desc-2-removed">Remove</a>
  </div>
</div>

Upvotes: 1

Louys Patrice Bessette
Louys Patrice Bessette

Reputation: 33933

You have to loop throught all the remaining divPhase, right after the removal on click... To re-number them.

So that is a big loop.
I'm really unsure that this is usefull to do it.
But here is how it can be done anyway.

$(".removeLink").on("click",function(){
  $(this).closest(".divPhase").remove();

  var divPhase = $(document).find(".divPhase");

  for(i=0;i<divPhase.length;i++){
    var j= i+1;
    divPhase.eq(i).attr("id","div"+j);

    // Row class
    var row = divPhase.eq(i).find(".row");
    row.attr("class","row margin-top-"+j);

    // Labels
    var labels = divPhase.eq(i).find("label");
    for(k=0;k<labels.length;k++){
      var labelHtml = labels.eq(k).html();
      labels.eq(k).html(labelHtml.substr(0,labelHtml.length-2)+j+":");
    }

    // Textareas
    var textareas = divPhase.eq(i).find("textarea");
    for(k=0;k<textareas.length;k++){
      var textareaId = textareas.eq(k).attr("id");
      textareas.eq(k).attr("id",textareaId.substr(0,textareaId.length-1)+j);

      var textareaName = textareas.eq(k).attr("name");
      textareas.eq(k).attr("name",textareaName.substr(0,textareaName.length-1)+j);
    }

    // Remove link
    var removeLinkHtml = divPhase.eq(i).find(".removeLink").html();
    divPhase.eq(i).find(".removeLink").html(removeLinkHtml.substr(0,removeLinkHtml.length-1)+j);
  }
});

CodePen

Upvotes: 1

Related Questions