Dimitrios Desyllas
Dimitrios Desyllas

Reputation: 10134

How I can display a dynamic popover with content upon value Copy?

I am trying to copy a value into clipboard:

/**
 * If not direct clipboard manipulation supported from browser, use a alternate approach
 * It is used upon copyTextToClipboard function.
 *
 * Function was seen in: https://stackoverflow.com/a/30810322/4706711
 *
 * @param {String} text
 */
function fallbackCopyTextToClipboard(text, callback) {
  var textArea = document.createElement("textarea");
  textArea.value = text;

  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    if (successful) {
      callback(null, text);
    } else {
      callback("Usucessfull copying of the value", text);
    }
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    callback(err, text);
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}

/**
 * Copy text into clipboard.
 *
 * Function from: https://stackoverflow.com/a/30810322/4706711
 *
 * @param {String} text
 */
function copyTextToClipboard(text, callback) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    callback(null, text);
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    callback(err, text);
    console.error('Async: Could not copy text: ', err);
  });
}

$(document).ready(() => {

  $(".btn-copy").on("click", (e) => {
    const element = e.target;
    const text = $(element).data('val');

    copyTextToClipboard(text, (err, text) => {
      alert(`Copied value ${text}`)
      //Display a popover here
    });
  });
})
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>


<button class="btn btn-primary btn-copy" data-val="Copy">
  Copy Value
</button>

But In my case Instead of alert I want to display a bootstrap5.3 Popover once copied. How I can do that? I want the popover to be displayed dynamically with a dynamic content. Is there a way to do this?

The bootstrap version is 5.3.

Upvotes: 0

Views: 132

Answers (1)

Dimitrios Desyllas
Dimitrios Desyllas

Reputation: 10134

In order to acheive that you need to render the popover as follows:

/**
 * If not direct clipboard manipulation supported from browser, use a alternate approach
 * It is used upon copyTextToClipboard function.
 *
 * Function was seen in: https://stackoverflow.com/a/30810322/4706711
 *
 * @param {String} text
 */
function fallbackCopyTextToClipboard(text, callback) {
  var textArea = document.createElement("textarea");
  textArea.value = text;

  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    if (successful) {
      callback(null, text);
    } else {
      callback("Usucessfull copying of the value", text);
    }
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    callback(err, text);
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}

/**
 * Copy text into clipboard.
 *
 * Function from: https://stackoverflow.com/a/30810322/4706711
 *
 * @param {String} text
 */
function copyTextToClipboard(text, callback) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    callback(null, text);
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    callback(err, text);
    console.error('Async: Could not copy text: ', err);
  });
}

$(document).ready(() => {

  $(".btn-copy").on("click", (e) => {
    const element = e.target;
    const text = $(element).data('val');

    copyTextToClipboard(text, (err, text) => {
      const popover = new bootstrap.Popover(element, {
        content: `Copied value ${text}`,
        delay: {
          "hide": 500
        },
        'placement': "bottom"
      });

      popover.show();
      setTimeout(() => {
        popover.hide()
      }, 1000);
    });
  });
})
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>


<button class="btn btn-primary btn-copy" data-val="Copy">
  Copy Value
</button>

Pay attetnion into this section in code above:

 const popover = new bootstrap.Popover(element, {
        content: `Copied value ${text}`,
        'placement': "bottom"
      });

      popover.show();
      setTimeout(() => {
        popover.hide()
      }, 1000);

What I do is I place the popover's content into content setting whereas I use setTimeout and its callback to hide it.

Upvotes: -1

Related Questions