Share via


How to copy and paste HTML (HTML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

Copying and pasting HTML content is different from other basic formats such as text or a link. The main challenge is that the content might contain references to other content. For example, it might contain img tags whose src attributes refer to locally-stored image files. When users copy this content, they expect to include both the text and the images. Apps that support copying and pasting HTML need to consider how to handle these references to ensure that users copy and paste the content they want.

To help you copy and paste HTML in a way that users expect, the Windows.ApplicationModel.DataTransfer namespace includes a few functions that help capture referenced elements, such as images. We'll show you how.

Check out our Clipboard sample app for comprehensive examples that show how to copy and paste other types of data.

What you need to know

Technologies

Prerequisites

  • You should be familiar with Quickstart: Clipboard basics.
  • You should know how to use JavaScript to identify HTML that a user has selected, and find instances of child elements like img tags within that selection.
  • You should be familiar with the Visual Studio and its associated templates.
  • You should be familiar with JavaScript.

Copying HTML to the Clipboard

  1. Create the DataPackage object.

    var dataPackage = new Windows.ApplicationModel.DataTransfer.DataPackage();
    
  2. Get the HTML content.

    Here we get content from an HTML element:

    var htmlFragment = document.getElementById("htmlTextToCopy").innerHTML;
    
  3. Prepare the HTML content for Clipboard operations.

    Use the HtmlFormatHelper.CreateHtmlFormat method to prepare the HTML content. This method adds the necessary headers and ensures that the HTML is formatted correctly for Clipboard operations.

    var htmlFormat = Windows.ApplicationModel.DataTransfer.HtmlFormatHelper.createHtmlFormat(htmlFragment);
    
  4. Add the HTML content to the DataPackage object.

    dataPackage.setHtmlFormat(htmlFormat);
    
  5. Populate the resource map with content references.

    If the user selected HTML that contains references to other content, such as locally-stored image files, you need to add the references to the DataPackage.ResourceMap property. Here are the steps needed to add an image reference:

    1. First, get the path information from the src attribute of the img tag embedded in the HTML content.
    2. Convert the path information to Uniform Resource Identifier (URI).
    3. Get a RandomAccessStreamReference object for the local image file.
    4. Add the RandomAccessStreamReference to the DataPackage.ResourceMap property.
    var imagePath = document.getElementById("localImage").src;
    var imageUri = new Windows.Foundation.Uri(imagePath);
    var streamRef = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(imageUri);
    dataPackage.resourceMap.insert(imagePath, streamRef);
    
  6. Copy the content to the Clipboard.

    Windows.ApplicationModel.DataTransfer.Clipboard.setContent(dataPackage);
    

Pasting HTML from the Clipboard

  1. Get the contents of the clipboard.

    var dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.getContent();
    
  2. Check whether the Clipboard contains HTML data.

    if (dataPackageView.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.html)) {
       ...
    }
    
  3. If the Clipboard contains HTML, retrieve it and add it to the Document Object Model (DOM) as indicated by the user.

    Caution  Be aware that HTML from another app is not trusted and you shouldn't display it unless you're sure the HTML doesn't have any dynamic content. Use the DataTransfer.HtmlFormatHelper.GetStaticFragment method to get shared HTML content without any dynamic elements such as script tags.

     

    
    var htmlFragment = Windows.ApplicationModel.DataTransfer.HtmlFormatHelper.getStaticFragment(htmlFormat);
    document.getElementById("htmlOutput").innerHTML = htmlFragment;
    
  4. Replace local image file URLs, if any, with the contents of the resource map by following these steps:

    1. Check the HTML for embedded img tags.
    2. If img tags are present, retrieve the RandomAccessStreamReference objects from the resource map.
    3. Replace the contents of the src attributes of the img tags with the URLs from the RandomAccessStreamReference objects.
    
    ...
    
    var images = document.getElementById("htmlOutput").getElementsByTagName("img");
    
    // Check first if there are any images (img tags) in the fragment, because
                // calling the getResourceMapAsync method can be resource intensive.
                if (images.length > 0) {
                    dataPackageView.getResourceMapAsync().done(function (resourceMap) {
    
                        // Check whether the resourceMap contains any items.
                        if (resourceMap.size > 0) {
                            for (var i = 0, len = images.length; i < len; i++) {
                                var imageElement = images[i];
    
                                // Look up RandomAccessStreamReference value corresponding to this 
                                // image's SRC property.
                                var streamRef = resourceMap.lookup(imageElement.getAttribute("src"));
                                if (streamRef) {
                                    // Generate blob URL, and replace contents of the SRC property.
                                    replaceSrcURL(imageElement, streamRef);
                                }
                            }
                        }
                    });
    
                }
    ...
    
    function replaceSrcURL(imageElement, streamRef) {
        // Map the image element's src to a corresponding blob URL generated from the streamReference.
        streamRef.openReadAsync().done(function (imageStream) {
            var blobObject = 
                window.MSApp.createBlobFromRandomAccessStream(imageStream.contentType, imageStream);
            var blobUrl = window.URL.createObjectURL(blobObject, { oneTimeOnly: true });
            imageElement.src = blobUrl;
        }, function (e) {
             displayError("Error opening stream corresponding to the image element with SRC=\"" + 
                 imageElement.getAttribute("src") + "\". Error: " + e);
        });
    }
    

Complete examples

This example shows how to copy HTML with an embedded image to the Clipboard.

function copyHTML() {
    // Create the DataPackage object.
    var dataPackage = new Windows.ApplicationModel.DataTransfer.DataPackage();

    // Get the HTML content of an element.
    var htmlFragment = document.getElementById("htmlTextToCopy").innerHTML;

    // Prepare the HTML for Clipboard operations.
    var htmlFormat = 
        Windows.ApplicationModel.DataTransfer.HtmlFormatHelper.createHtmlFormat(htmlFragment);
    if (htmlFormat !== "") {
        // Add the HTML to the DataPackage object
        dataPackage.setHtmlFormat(htmlFormat);

        // Populate the resourceMap with RandomAccessStreamReference objects 
        // corresponding to the local image file embedded in the HTML.
        var imagePath = document.getElementById("someEmbeddedImage").src;
        var imageUri = new Windows.Foundation.Uri(imagePath);
        var streamRef = Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(imageUri);
        dataPackage.resourceMap.insert(imagePath, streamRef);
    }

    try {
        // Copy the HTML content to Clipboard.
        Windows.ApplicationModel.DataTransfer.Clipboard.setContent(dataPackage);
        displayStatus("Text and HTML formats have been copied to Clipboard");
    } catch (e) {
        // Copying data to Clipboard can potentially fail if, for example another app is holding
        // the Clipboard open.
        displayError("Error copying content to Clipboard: " + e + ". Try again.");
    }
}

This example shows how to get HTML stored in the Clipboard, along with any images referenced in the HTML content.

function pasteHTML() {

    var dataPackageView = Windows.ApplicationModel.DataTransfer.Clipboard.getContent();

    if (dataPackageView.contains(Windows.ApplicationModel.DataTransfer.StandardDataFormats.html)) {

        // Get the HTML Format (CF_HTML) from DataPackageView.
        dataPackageView.getHtmlFormatAsync().done(function (htmlFormat) {

            // Extract the HTML fragment.
            var htmlFragment = 
                Windows.ApplicationModel.DataTransfer.HtmlFormatHelper.getStaticFragment(htmlFormat);

            // Add the fragment to the DOM.
            document.getElementById("htmlOutput").innerHTML = htmlFragment;

            // Replace local image file URLs, if any, with the contents of the resourceMap.
            var images = document.getElementById("htmlOutput").getElementsByTagName("img");

            // Check first if there are any images (img tags) in the fragment, because
            // calling the getResourceMapAsync method can be resource intensive.
            if (images.length > 0) {
                dataPackageView.getResourceMapAsync().done(function (resourceMap) {

                    // Check whether the resourceMap contains any items.
                    if (resourceMap.size > 0) {
                        for (var i = 0, len = images.length; i < len; i++) {
                            var imageElement = images[i];
                     
                            // Look up RandomAccessStreamReference value corresponding to this 
                            // image's SRC property.
                            var streamRef = resourceMap.lookup(imageElement.getAttribute("src"));
                            if (streamRef) {
                                // Generate blob URL, and replace contents of the SRC property.
                                replaceSrcURL(imageElement, streamRef);
                            }
                        }
                    }
                });

            }

        }, function (e) {
            displayError("Error retrieving HTML format from Clipboard: " + e);
        });
    } else {
        document.getElementById("scenario1HtmlOutput").innerText = 
        "HTML format is not available in clipboard";
    }
}

function replaceSrcURL(imageElement, streamRef) {
    // Map the image element's src to a corresponding blob URL generated from the streamReference.
    streamRef.openReadAsync().done(function (imageStream) {
        var blobObject = 
            window.MSApp.createBlobFromRandomAccessStream(imageStream.contentType, imageStream);
        var blobUrl = window.URL.createObjectURL(blobObject, { oneTimeOnly: true });
        imageElement.src = blobUrl;
    }, function (e) {
         displayError("Error opening stream corresponding to the image element with SRC=\"" + 
             imageElement.getAttribute("src") + "\". Error: " + e);
    });
}

Quickstart: Clipboard basics

How to copy and paste files

How to copy and paste images

Guidelines and checklist for clipboard commands

DataPackage

Windows.ApplicationModel.DataTransfer

Clipboard sample app