क्लिपबोर्ड का ऐक्सेस अनब्लॉक किया जा रहा है

टेक्स्ट और इमेज के लिए ज़्यादा सुरक्षित, अनब्लॉक किए गए क्लिपबोर्ड का ऐक्सेस

क्लिपबोर्ड इंटरैक्शन के लिए, सिस्टम क्लिपबोर्ड को ऐक्सेस करने का पारंपरिक तरीका document.execCommand() था. हालांकि, यह बड़े पैमाने पर काम करता था, फिर भी डेटा को काटने और चिपकाने के इस तरीके के लिए शुल्क देना पड़ता था: क्लिपबोर्ड का ऐक्सेस सिंक्रोनस था और डीओएम में सिर्फ़ पढ़ा और लिखा जा सकता था.

छोटे हिस्से के टेक्स्ट के लिए यह ठीक है, लेकिन कई मामलों में क्लिपबोर्ड ट्रांसफ़र के लिए पेज को ब्लॉक करने से अच्छा अनुभव नहीं मिलता. कॉन्टेंट को सुरक्षित तरीके से चिपकाने से पहले, साफ़ करने या इमेज को डिकोड करने में समय लग सकता है. ब्राउज़र को, चिपकाए गए दस्तावेज़ से लिंक किए गए रिसॉर्स को लोड या इनलाइन करने की ज़रूरत हो सकती है. इससे डिस्क या नेटवर्क पर इंतज़ार करते समय पेज ब्लॉक हो जाएगा. मिक्स में अनुमतियां जोड़ने के बारे में सोचें, ताकि यह ज़रूरी हो कि क्लिपबोर्ड के ऐक्सेस का अनुरोध करते समय ब्राउज़र पेज को ब्लॉक कर दे. साथ ही, क्लिपबोर्ड इंटरैक्शन के लिए document.execCommand() के आस-पास लागू की गई अनुमतियां थोड़ी आसान होती हैं और अलग-अलग ब्राउज़र पर अलग-अलग होती हैं.

Async Clipboard API इन समस्याओं को ठीक करता है. इससे, अनुमतियों का एक ऐसा मॉडल मिलता है जो पेज को ब्लॉक नहीं करता. Async Clipboard API का इस्तेमाल ज़्यादातर ब्राउज़र पर टेक्स्ट और इमेज को हैंडल करने के लिए ही किया जा सकता है, लेकिन इसके लिए अलग-अलग तरह के टूल काम करते हैं. नीचे दिए गए हर सेक्शन के लिए, ब्राउज़र के साथ काम करने से जुड़ी खास जानकारी को ध्यान से पढ़ें.

कॉपी करें: क्लिपबोर्ड पर डेटा सेव करने की सेटिंग

writeText()

टेक्स्ट को क्लिपबोर्ड पर कॉपी करने के लिए, writeText() को कॉल करें. यह एपीआई एसिंक्रोनस है, इसलिए writeText() फ़ंक्शन ऐसा प्रॉमिस देता है जो पास किए गए टेक्स्ट को कॉपी किए जाने के आधार पर हल या अस्वीकार करता है:

async function copyPageUrl() {
  try {
    await navigator.clipboard.writeText(location.href);
    console.log('Page URL copied to clipboard');
  } catch (err) {
    console.error('Failed to copy: ', err);
  }
}

ब्राउज़र सहायता

  • 66
  • 79
  • 63
  • 78 जीबी में से

सोर्स

लिखें()

दरअसल, सामान्य write() तरीके के लिए writeText() सिर्फ़ एक आसान तरीका है. इसकी मदद से, क्लिपबोर्ड पर इमेज कॉपी भी की जा सकती है. writeText() की तरह, यह एसिंक्रोनस होता है और प्रॉमिस दिखाता है.

क्लिपबोर्ड पर इमेज लिखने के लिए, आपको इमेज की ज़रूरत blob के तौर पर होगी. इसका एक तरीका यह है कि fetch() का इस्तेमाल करके, सर्वर से इमेज का अनुरोध करें. इसके बाद, जवाब के लिए blob() को कॉल करें.

सर्वर से इमेज के लिए अनुरोध करना कई वजहों से ज़रूरी या मुमकिन नहीं होता है. अच्छी बात यह है कि इमेज को कैनवस पर भी बनाया जा सकता है और कैनवस'toBlob() तरीके को कॉल किया जा सकता है.

इसके बाद, write() तरीके में ClipboardItem ऑब्जेक्ट के कलेक्शन को पैरामीटर के तौर पर पास करें. फ़िलहाल, एक बार में सिर्फ़ एक इमेज पास की जा सकती है. हालांकि, हमारी कोशिश है कि आने वाले समय में हम कई इमेज के लिए भी यह सुविधा दें. ClipboardItem इमेज के MIME टाइप वाले ऑब्जेक्ट को कुंजी के तौर पर और ब्लॉब को वैल्यू के तौर पर लेता है. fetch() या canvas.toBlob() से मिले ब्लॉब ऑब्जेक्ट के लिए, blob.type प्रॉपर्टी में किसी इमेज का सही MIME टाइप अपने-आप शामिल हो जाता है.

try {
  const imgURL = '/images/generic/file.png';
  const data = await fetch(imgURL);
  const blob = await data.blob();
  await navigator.clipboard.write([
    new ClipboardItem({
      // The key is determined dynamically based on the blob's type.
      [blob.type]: blob
    })
  ]);
  console.log('Image copied.');
} catch (err) {
  console.error(err.name, err.message);
}

इसके अलावा, आपके पास ClipboardItem ऑब्जेक्ट में प्रॉमिस लिखा जा सकता है. इस पैटर्न के लिए, आपको पहले से ही डेटा के MIME टाइप की जानकारी होनी चाहिए.

try {
  const imgURL = '/images/generic/file.png';
  await navigator.clipboard.write([
    new ClipboardItem({
      // Set the key beforehand and write a promise as the value.
      'image/png': fetch(imgURL).then(response => response.blob()),
    })
  ]);
  console.log('Image copied.');
} catch (err) {
  console.error(err.name, err.message);
}

ब्राउज़र सहायता

  • 66
  • 79
  • 78 जीबी में से

सोर्स

कॉपी करने वाला इवेंट

अगर कोई उपयोगकर्ता क्लिपबोर्ड पर कॉपी करने की प्रक्रिया शुरू करता है और preventDefault() को कॉल नहीं करता है, तो copy इवेंट में clipboardData प्रॉपर्टी शामिल होती है, जिसके आइटम पहले से सही फ़ॉर्मैट में होते हैं. अगर आपको अपना लॉजिक लागू करना है, तो preventDefault() को कॉल करें, ताकि डिफ़ॉल्ट तरीका लागू न हो. इस मामले में, clipboardData खाली रहेगा. टेक्स्ट और इमेज वाले पेज के बारे में सोचें. जब उपयोगकर्ता सभी को चुनता है और क्लिपबोर्ड की कॉपी बनाने की प्रोसेस शुरू करता है, तो आपके पसंद के मुताबिक बनाए गए समाधान को टेक्स्ट खारिज करना चाहिए और सिर्फ़ इमेज को कॉपी करना चाहिए. नीचे दिए गए कोड सैंपल में दिखाए गए तरीके से, ऐसा किया जा सकता है. इस उदाहरण में यह नहीं बताया गया है कि Clipboard API के काम न करने पर, पुराने एपीआई पर वापस कैसे जाएं.

<!-- The image we want on the clipboard. -->
<img src="kitten.webp" alt="Cute kitten.">
<!-- Some text we're not interested in. -->
<p>Lorem ipsum</p>
document.addEventListener("copy", async (e) => {
  // Prevent the default behavior.
  e.preventDefault();
  try {
    // Prepare an array for the clipboard items.
    let clipboardItems = [];
    // Assume `blob` is the blob representation of `kitten.webp`.
    clipboardItems.push(
      new ClipboardItem({
        [blob.type]: blob,
      })
    );
    await navigator.clipboard.write(clipboardItems);
    console.log("Image copied, text ignored.");
  } catch (err) {
    console.error(err.name, err.message);
  }
});

copy इवेंट के लिए:

ब्राउज़र सहायता

  • 1
  • 12
  • 22
  • 3

सोर्स

ClipboardItem के लिए:

ब्राउज़र सहायता

  • 76
  • 79
  • 78 जीबी में से

सोर्स

चिपकाएं: क्लिपबोर्ड से डेटा पढ़ा जा रहा है

readText()

क्लिपबोर्ड पर मौजूद टेक्स्ट पढ़ने के लिए, navigator.clipboard.readText() को कॉल करें. इसके बाद, वापस किए गए प्रॉमिस का समाधान होने तक इंतज़ार करें:

async function getClipboardContents() {
  try {
    const text = await navigator.clipboard.readText();
    console.log('Pasted content: ', text);
  } catch (err) {
    console.error('Failed to read clipboard contents: ', err);
  }
}

ब्राउज़र सहायता

  • 66
  • 79
  • 78 जीबी में से

सोर्स

पढ़ें()

navigator.clipboard.read() वाला तरीका भी एसिंक्रोनस भी है और यह वादा करता है. क्लिपबोर्ड पर मौजूद किसी इमेज को पढ़ने के लिए, ClipboardItem ऑब्जेक्ट की सूची लें, फिर उन्हें दोहराएं.

हर ClipboardItem में अलग-अलग तरह का कॉन्टेंट हो सकता है. इसलिए, आपको for...of लूप का इस्तेमाल करके, कॉन्टेंट को टाइप की सूची में फिर से दोहराना होगा. हर टाइप के लिए, सही ब्लॉब पाने के लिए, मौजूदा टाइप के साथ getType() वाले तरीके को तर्क के तौर पर कॉल करें. पहले की तरह, यह कोड इमेज से नहीं जुड़ा है और आने वाले समय में अपलोड किए जाने वाले अन्य फ़ाइल टाइप के साथ काम करेगा.

async function getClipboardContents() {
  try {
    const clipboardItems = await navigator.clipboard.read();
    for (const clipboardItem of clipboardItems) {
      for (const type of clipboardItem.types) {
        const blob = await clipboardItem.getType(type);
        console.log(URL.createObjectURL(blob));
      }
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
}

ब्राउज़र सहायता

  • 66
  • 79
  • 78 जीबी में से

सोर्स

चिपकाई गई फ़ाइलों के साथ काम करना

यह उपयोगकर्ताओं के लिए क्लिपबोर्ड कीबोर्ड शॉर्टकट, जैसे कि ctrl+c और ctrl+v का इस्तेमाल करने के लिए उपयोगी है. Chromium क्लिपबोर्ड पर रीड-ओनली फ़ाइलों को नीचे बताए गए तरीके से दिखाता है. यह तब ट्रिगर होता है, जब उपयोगकर्ता ऑपरेटिंग सिस्टम के डिफ़ॉल्ट पेस्ट शॉर्टकट पर क्लिक करता है या जब उपयोगकर्ता ब्राउज़र के मेन्यू बार में बदलाव करें और फिर चिपकाएं पर क्लिक करता है. किसी और प्लंबिंग कोड की ज़रूरत नहीं है.

document.addEventListener("paste", async e => {
  e.preventDefault();
  if (!e.clipboardData.files.length) {
    return;
  }
  const file = e.clipboardData.files[0];
  // Read the file's contents, assuming it's a text file.
  // There is no way to write back to it.
  console.log(await file.text());
});

ब्राउज़र सहायता

  • 3
  • 12
  • 3.6
  • 4

सोर्स

चिपकाने का इवेंट

जैसा कि पहले बताया गया है, Clipboard API के साथ काम करने के लिए इवेंट शुरू किए जाने हैं. हालांकि, फ़िलहाल, मौजूदा paste इवेंट का इस्तेमाल किया जा सकता है. यह क्लिपबोर्ड टेक्स्ट पढ़ने के नए एसिंक्रोनस तरीकों के साथ अच्छी तरह काम करता है. copy इवेंट की तरह, preventDefault() को कॉल करना न भूलें.

document.addEventListener('paste', async (e) => {
  e.preventDefault();
  const text = await navigator.clipboard.readText();
  console.log('Pasted text: ', text);
});

ब्राउज़र सहायता

  • 1
  • 12
  • 22
  • 3

सोर्स

कई तरह के MIME टाइप हैंडल करना

ज़्यादातर मामलों में, एक कट या कॉपी करने के लिए, क्लिपबोर्ड पर कई डेटा फ़ॉर्मैट सेव होते हैं. इसकी दो वजहें हैं: ऐप्लिकेशन डेवलपर के तौर पर, आपके पास यह जानने का कोई तरीका नहीं होता कि उपयोगकर्ता उस ऐप्लिकेशन की क्षमताओं के बारे में क्या जानते हैं जिसमें उपयोगकर्ता टेक्स्ट या इमेज कॉपी करना चाहता है. साथ ही, कई ऐप्लिकेशन में स्ट्रक्चर्ड डेटा को सादे टेक्स्ट के तौर पर चिपकाने की सुविधा होती है. आम तौर पर, यह उपयोगकर्ताओं को बदलाव करें मेन्यू आइटम के साथ दिखाया जाता है. मेन्यू आइटम में चिपकाएं और मैच की स्टाइल या फ़ॉर्मैट किए बिना चिपकाएं जैसे नाम होते हैं.

नीचे दिए गए उदाहरण में, इसे करने का तरीका बताया गया है. इस उदाहरण में इमेज का डेटा पाने के लिए fetch() का इस्तेमाल किया जाता है. हालांकि, यह <canvas> या फ़ाइल सिस्टम ऐक्सेस एपीआई से भी मिल सकता है.

async function copy() {
  const image = await fetch('kitten.png').then(response => response.blob());
  const text = new Blob(['Cute sleeping kitten'], {type: 'text/plain'});
  const item = new ClipboardItem({
    'text/plain': text,
    'image/png': image
  });
  await navigator.clipboard.write([item]);
}

सुरक्षा और अनुमतियां

क्लिपबोर्ड ऐक्सेस ने हमेशा ब्राउज़र के लिए सुरक्षा चिंता का विषय बना हुआ है. सही अनुमतियों के बिना, कोई पेज नुकसान पहुंचाने वाले हर तरह के कॉन्टेंट को उपयोगकर्ता के क्लिपबोर्ड पर कॉपी कर सकता है. इससे, कॉन्टेंट चिपकाने पर नुकसान पहुंचाने वाले नतीजे मिल सकते हैं. ऐसे वेब पेज के बारे में सोचिए जो आपके क्लिपबोर्ड पर rm -rf / या डिकंप्रेशन बम की इमेज को चुपचाप कॉपी करता है.

ब्राउज़र की सूचना, उपयोगकर्ता से क्लिपबोर्ड की अनुमति मांगती है.
Clipboard API के लिए अनुमति का अनुरोध.

वेब पेजों को क्लिपबोर्ड पर पढ़े जाने का ऐक्सेस देना, और भी मुश्किल होता है. उपयोगकर्ता, पासवर्ड और निजी जानकारी जैसी संवेदनशील जानकारी को क्लिपबोर्ड पर नियमित रूप से कॉपी करते हैं. इसे उपयोगकर्ता की जानकारी के बिना किसी भी पेज पर पढ़ा जा सकता है.

कई नए एपीआई की तरह, Clipboard API सिर्फ़ उन पेजों के लिए काम करता है जो एचटीटीपीएस पर दिखाए जाते हैं. गलत इस्तेमाल को रोकने के लिए, क्लिपबोर्ड को सिर्फ़ तब ऐक्सेस किया जा सकता है, जब कोई पेज ऐक्टिव टैब पर सेट हो. सक्रिय टैब में मौजूद पेज, अनुमति का अनुरोध किए बिना ही क्लिपबोर्ड पर लिख सकते हैं, लेकिन क्लिपबोर्ड से पढ़ने के लिए हमेशा अनुमति की ज़रूरत होती है.

कॉपी करने और चिपकाने की अनुमतियां, अनुमतियों के एपीआई में जोड़ी गई हैं. पेजों को clipboard-write की अनुमति अपने-आप तब मिल जाती है, जब वे चालू टैब होते हैं. clipboard-read अनुमति का अनुरोध करना ज़रूरी है. ऐसा करने के लिए, क्लिपबोर्ड का डेटा ऐक्सेस करें. नीचे दिया गया कोड यह दिखाता है कि:

const queryOpts = { name: 'clipboard-read', allowWithoutGesture: false };
const permissionStatus = await navigator.permissions.query(queryOpts);
// Will be 'granted', 'denied' or 'prompt':
console.log(permissionStatus.state);

// Listen for changes to the permission state
permissionStatus.onchange = () => {
  console.log(permissionStatus.state);
};

यह भी कंट्रोल किया जा सकता है कि allowWithoutGesture विकल्प का इस्तेमाल करके, काटने या चिपकाने की प्रोसेस शुरू करने के लिए उपयोगकर्ता के जेस्चर की ज़रूरत है या नहीं. इस वैल्यू की डिफ़ॉल्ट वैल्यू, ब्राउज़र के हिसाब से अलग-अलग होती है. इसलिए, आपको इसे हमेशा शामिल करना चाहिए.

यहां बताया गया है कि Clipboard API का एसिंक्रोनस स्वभाव बहुत काम का है: क्लिपबोर्ड डेटा को पढ़ने या लिखने की कोशिश करने से, उपयोगकर्ता को अपने-आप इसकी अनुमति मिल जाती है. हालांकि, ऐसा तब ही होता है, जब उपयोगकर्ता ने पहले से अनुमति न दी हो. एपीआई, प्रॉमिस पर आधारित होता है. इसलिए, यह पूरी तरह से पारदर्शी है. साथ ही, क्लिपबोर्ड की अनुमति न देने पर, प्रॉमिस अस्वीकार कर दिया जाता है, ताकि पेज सही तरीके से जवाब दे सके.

ब्राउज़र क्लिपबोर्ड को ऐक्सेस करने की अनुमति सिर्फ़ तब देते हैं, जब कोई पेज चालू टैब हो. इसलिए, आपको दिखेगा कि अगर यहां दिए गए कुछ उदाहरण सीधे ब्राउज़र के कंसोल में चिपकाए जाते हैं, तो वे नहीं चलते, क्योंकि डेवलपर टूल खुद ही ऐक्टिव टैब होते हैं. एक ट्रिक है: setTimeout() का इस्तेमाल करके क्लिपबोर्ड का ऐक्सेस रोकें. इसके बाद, फ़ंक्शन कॉल करने से पहले, पेज पर फ़ोकस करने के लिए तुरंत क्लिक करें:

setTimeout(async () => {
  const text = await navigator.clipboard.readText();
  console.log(text);
}, 2000);

अनुमतियों से जुड़ी नीति का इंटिग्रेशन

iframe में एपीआई का इस्तेमाल करने के लिए, आपको इसे अनुमति नीति की मदद से चालू करना होगा. यह एक ऐसा तरीका है जिससे ब्राउज़र की अलग-अलग सुविधाओं और एपीआई को चुनिंदा तरीके से चालू या बंद किया जा सकता है. इसका मतलब है कि आपको अपने ऐप्लिकेशन की ज़रूरतों के मुताबिक, clipboard-read या clipboard-write में से किसी एक या दोनों को पास करना होगा.

<iframe
    src="index.html"
    allow="clipboard-read; clipboard-write"
>
</iframe>

सुविधा की पहचान करने की सुविधा

सभी ब्राउज़र पर Async Clipboard API का इस्तेमाल करने के लिए, navigator.clipboard की जांच करें और पहले वाले तरीकों पर वापस जाएं. उदाहरण के लिए, यहां बताया गया है कि दूसरे ब्राउज़र को शामिल करने के लिए पेस्ट करने की सुविधा कैसे लागू की जा सकती है.

document.addEventListener('paste', async (e) => {
  e.preventDefault();
  let text;
  if (navigator.clipboard) {
    text = await navigator.clipboard.readText();
  }
  else {
    text = e.clipboardData.getData('text/plain');
  }
  console.log('Got pasted text: ', text);
});

यह पूरी कहानी नहीं है. Async Clipboard API से पहले, सभी वेब ब्राउज़र में कॉपी करने और चिपकाने का तरीका अलग-अलग था. ज़्यादातर ब्राउज़र में, document.execCommand('copy') और document.execCommand('paste') का इस्तेमाल करके, ब्राउज़र की अपनी 'कॉपी करें और चिपकाएं' ट्रिगर हो सकती है. अगर कॉपी किया जाने वाला टेक्स्ट एक ऐसी स्ट्रिंग है जो DOM में मौजूद नहीं है, तो उसे DOM में इंजेक्ट किया जाना चाहिए और चुना जाना चाहिए:

button.addEventListener('click', (e) => {
  const input = document.createElement('input');
  input.style.display = 'none';
  document.body.appendChild(input);
  input.value = text;
  input.focus();
  input.select();
  const result = document.execCommand('copy');
  if (result === 'unsuccessful') {
    console.error('Failed to copy text.');
  }
  input.remove();
});

डेमो

नीचे दिए गए डेमो में, Async Clipboard API का इस्तेमाल किया जा सकता है. Glitch पर, टेक्स्ट डेमो या इमेज डेमो को रीमिक्स करके एक्सपेरिमेंट किया जा सकता है.

पहला उदाहरण टेक्स्ट को क्लिपबोर्ड पर चालू और बंद करने के बारे में बताता है.

इमेज के साथ एपीआई को आज़माने के लिए, इस डेमो का इस्तेमाल करें. याद रखें कि सिर्फ़ PNG फ़ॉर्मैट काम करते हैं और कुछ ही ब्राउज़र में इस्तेमाल किए जा सकते हैं.

स्वीकार हैं

एसिंक्रोनस क्लिपबोर्ड एपीआई को Darwin Huang और Gary Kačmarčík ने लागू किया है. डार्विन ने इस वीडियो का डेमो भी दिया है. इस लेख के हिस्सों की समीक्षा करने के लिए, क्यारिक और गैरी Kačmarčík का एक बार फिर से धन्यवाद.

Unस्प्लैश पर मार्कस विंकलर की हीरो इमेज.