skip to Main Content

I want to change ID="value" with another id value from tag and I also want to change the value where this name used as target attribute value if there in code

$('div[id]').each(function() {
  $(this).attr("id", "newValueWithRandomNumber")
  // I can change only ID value 

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="example1"> I can easily change ID name here </div>


<div id="example2"> I have to find dynamically where this ID used as target value </div>
<div data-bs-target="example2"> button </div>
<div data-*any="example2"> button </div>
<div *any="example2"> button </div>

2

Answers


  1. I really don’t like this approach, but if you can’t alter the HTML to use classes and make your DOM references that way, you can scan the DOM for the string you wish to replace and replace all occurrences with .innerHTML. This approach could of course be customized to search just parts of the DOM rather than the whole thing.

    document.body.innerHTML = document.body.innerHTML.replaceAll('="example2"','="example3"');
    
    console.log($("body").html());
    <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div id="example1"> I can easily change ID name here </div>
    
    
    <div id="example2"> I have to find dynamically where this ID used as target value </div>
    <div data-bs-target="example2"> button </div>
    <div data-*any="example2"> button </div>
    <div *any="example2"> button </div>
    </body>
    Login or Signup to reply.
  2. You can do this but it is not super fast so you want to limit the scope (not document or body for instance). Two examples but same functional result.
    NOTE: Here I dealt with the potentially harder example of data attributes but a similar process could be done for other attributes.

    Second example I added some CSS to show the NOT targeted attribute did not change value;

    I put a LOT of comments and console logs in the first example:

    function toCamelCase(str) {
      return str.replace(/-([a-z])/g, (x, up) => up.toUpperCase());
    }
    
    function datasetNameToCamelCase(str) {
      const dSplit = str.split('data-')[1];
      console.log('split:', dSplit);
      return toCamelCase(dSplit);
    }
    
    let newNumber = 0;
    let params = [newNumber];
    let updatedID = "";
    $('#example2')
      .each(function(index) {
        let aNumber = params[0];
        const $el = $(this);
        console.log(this);
        let myId = $el.attr("id");
        $el.prop("id", myId + aNumber);
        let newID = this.id + "-" + aNumber;
        this.id = newID;
        console.log("id three ways newID:", newID, this.id, $el.prop("id"));
        /* filter for elements with Limited scope for speed */
        let $targets = $('body')
          .find('.search-scope')
          .find("*").filter(function() {
            let tgt = this;
            // match JUST the data-* attributes value of the id
            let attrs = [].filter.call(tgt.attributes, at => /^data-/.test(at.name)).filter((t) => t.value == myId);
            return !!attrs.length;
          });
        const hasTargets = !!$targets.length;
        console.log("Targets:", hasTargets, $targets.length);
        $targets.each(function(index) {
          let tg = this;
          let attrb = [].filter.call(tg.attributes, at => /^data-/.test(at.name)).filter((t) => t.value == myId);
          //console.log("data el:",attrb.length);
          attrb.forEach(function(dataAttribute) {
            let cased = datasetNameToCamelCase(dataAttribute["name"]);
            console.log("cased:", cased);
            /* we know we are working with data- so we can use the
             jQuery .data();  
             or the dataset 
             or the .attr() OR the dataAttribute["name"]
             or just the value as dataAttribute.value
            */
            console.log('dataAttribute:',
              "rntlocalName:", dataAttribute.localName,
              "rntname:", dataAttribute["name"],
              "rntattr():", $(tg).attr(dataAttribute["name"]),
              "rntvalue:", dataAttribute.value);
            const attrThing = $(tg).attr(dataAttribute["name"]);
            const dataThing = $(tg).data(cased);
            const dataSet = tg.dataset[cased];
            console.log("TargetDataset:", attrThing, dataThing, dataSet);
            dataAttribute.value = newID;
            updatedID = newID;
            $(tg).addClass("target");
          });
        });
        aNumber++;
        if (!hasTargets) {
          console.log("No targets found any:", hasTargets);
        }
        // show we just changed the passed one:
        console.log("next:", aNumber, newNumber);
        $('#' + updatedID).addClass("target-source");
      }, params);
    .target-source {
      border: solid 1px #00ff00;
    }
    
    .target {
      border: double 4px #00ff00;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="search-scope">
      <div id="example1">I can easily change ID name here</div>
      <div id="example2">I have to find dynamically where this ID used as target value</div>
      <div data-bs-target="example2">button bs</div>
      <div data-my-fun-any="example2">button my-fun</div>
      <div data-any-giraffe-any="example2">button giraffe</div>
      <div data-any-giraffe-any="example2notme">button giraffe no</div>
      <div my-fun-any="example2">button fun </div>
      <div cheese-any="example2">button cheese</div>
    </div>

    Less noise, but same thing functionally.

    function toCamelCase(str) {
      return str.replace(/-([a-z])/g, (x, up) => up.toUpperCase());
    }
    
    function datasetNameToCamelCase(str) {
      const dSplit = str.split('data-')[1];
      return toCamelCase(dSplit);
    }
    
    let newNumber = 0;
    let params = [newNumber];
    
    $('#example2')
      .each(function(index) {
        let aNumber = params[0];
        const $el = $(this);
        const myId = $el.attr("id");
        $el.prop("id", myId + aNumber)
          .addClass("target-source");
        const newID = this.id + "-" + aNumber;
        this.id = newID;
        let $targets = $('body')
          .find('.search-scope')
          .find("*").filter(function() {
            let attrs = [].filter.call(this.attributes, at => /^data-/.test(at.name)).filter((t) => t.value == myId);
            return !!attrs.length;
          });
        $targets.each(function(index, tg) {
          [].filter.call(tg.attributes, at => /^data-/.test(at.name))
            .filter((t) => t.value == myId)
            .forEach(function(dataAttribute) {
              let cased = datasetNameToCamelCase(dataAttribute["name"]);
              dataAttribute.value = newID;
              $(tg).addClass("target");
            });
        });
        aNumber++;
      }, params);
    .target-source {
      border: solid 1px #00ff00;
    }
    
    .target {
      border: double 4px #00ff00;
    }
    
    [data-more-noise="freedom"] {
      background-color: #00ff0020;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="search-scope">
      <div id="example1">I can easily change ID name here</div>
      <div id="example2">I have to find dynamically where this ID used as target value</div>
      <div data-bs-target="example2">button bs</div>
      <div data-my-fun-any="example2">button my-fun</div>
      <div data-any-giraffe-any="example2">button giraffe</div>
      <div data-any-giraffe-any="example2" data-more-noise="freedom">button giraffe Free</div>
      <div data-any-giraffe-any="example2notme">button giraffe no</div>
      <div my-fun-any="example2">button fun </div>
      <div cheese-any="example2">button cheese</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search