Create a JavaScript plugin to highlight and tweet text

Create a JavaScript plugin to highlight and tweet text
Check out my Github for my free-to-read JavaScript Ebook that covers all the new features from ES6 to 2019. If you want find a great place for interactive tutorials, i recommend Educative where I'm currently finishing to build my JavaScript course.
This website contains affiliate links. See my disclosure about affiliate links here

Create a plugin to highlight and tweet text

Many times I found myself reading a passage on a website and thinking I wanted to share that with my friends or random people of the internet, but few are the times where the website facilitated that process for me.

Usually, I would have to copy the passage I wanted to share, go on Twitter and tweet it but we all know that most people are lazy so, if you want your user to tweet content from your articles/blogs, etc... in this tutorial, I will teach you how to create a simple plugin to do that.

Alternatively, if you don't want to bother with coding it yourself, I've already packaged it for you and you can find it on npm at highlight-to-tweet.

Credits for most of the idea and the code go to this user on WebFlow. I mostly transformed the JQuery code into a native JavaScript code and published it as an npm package.

The plugin we are going to build will work in the following way:

  • A user highlight some text on your page
  • They are prompted to tweet it with a button
  • They click the button and they can tweet it, all without leaving your site

Create the tweetHighlighted function

Now that you are ready to start, let's open your JavaScript file and start with:

document.addEventListener('DOMContentLoaded', () => {

    window.tweetHighlighted = () => {
        // our function will be built here
    }

    // we call it once the page loads
    window.tweetHighlighted()
})

The first thing we want to do know is to define some properties that will come in handy later on. Inside of the window.tweetHighlighted = () => { function, we want to add this code:

const settings = {
    node: "<a href='#'>Tweet</a>",
    maxLength: 280,    
    extra: null,
    via: null,
    popupArgs:'width=400,height=400,toolbar=0,location=0',
}

These are the basic settings of our plugin:

  • node defines the element that will be contained in the button that pops up
  • maxLength is the max length allowed for the tweet, here I've set it as 280 because that's the max allowed for a tweet, but if you want to set it lower you can do it
  • extra is simply some extra text that you want to include in your tweets
  • via defines the handler for twitter, if you want to be tagged whenever a user tweets something from your site
  • popupArgs is used to define the twitter popup

Our next step will be to create a button, add it to the DOM and give an event listener to it.

Continuing after the code we just wrote, add this:

let url = '';
let text = '';
const shareButton = document.createElement('div');
shareButton.style.display = 'none';
shareButton.addEventListener('click', (e) => {
    e.preventDefault();
    e.stopPropagation();
    window.open(url, '_blank', settings.popupArgs);
})
const body = document.querySelector('body');
body.appendChild(shareButton);

Firstly, we defined two empty variables that will hold our url and text for the tweet.

Secondly, we created a new div element and assign it to our variable shareButton.

We then hid it with display:'none' and added an event listener to it to listen for click events.

When a user clicks our button we use stopPropagation to avoid the click event to bubble down to the a tag that we assigned above to the node in our settings and we also call window.open passing the url that will be populated later and our arguments to define the size of the window to open.

After that, we are simply adding this newly created element to the body of our page.

One thing you may be wondering is how we are going to identify when the user highlights texts on the page.

The answer to that is simple, we will use the mouseup event and check if the user selected something.

Add event listeners to the function

Continuing from where we left, let's add this code:

document.addEventListener('mouseup', (e) => {
    text = getSelectedText();
    const btnExists = shareButton.style.display !== 'none';
    if (btnExists || !text.length){
        return;
    } else {
        appendShareButton(e)
    }
})

 const getSelectedText = () => {
    if (window.getSelection) {
        return window.getSelection().toString();
    } else if (document.selection) {
        return document.selection.createRange().text;
    }
    return '';
};

Awesome, these two functions will ensure that when the user triggers the mouseup event, if there is some text highlighted, we will capture it, store it in our text variable and call the function appendShareButton to add that button to the DOM.

Let's continue and define that function:

const appendShareButton = (e) => {
               
    url = getTweetURL(text, settings.extra, settings.via);

    shareButton.innerHTML = '';
    shareButton.innerHTML += settings.node;
    shareButton.innerHTML += tweetIcon;
    if(settings.cssClassess && settings.cssClassess.length){
        shareButton.classList.add(settings.cssClassess);
    }
    shareButton.style.top = `${e.pageY}px`;
    shareButton.style.left = `${e.pageX}px`;
    shareButton.style.position = 'absolute';
    shareButton.style.cursor = 'pointer';
    shareButton.style.display = 'flex';
    shareButton.style.justifyContent = 'space-between';
    shareButton.style.alignContent = 'center';
    shareButton.style.alignItems = 'center';
    shareButton.style.opacity = 0;

    shareButton.style.fontFamily = 'Arial, Helvetica, sans-serif';
    shareButton.style.backgroundColor = '#3898EC';
    shareButton.style.padding = '10px 15px';
    shareButton.style.width = '100px'
    shareButton.style.borderRadius = '5px';
    shareButton.style.color = 'white';
    shareButton.firstChild.style.color = 'white';
    shareButton.firstChild.style.textDecoration = 'none';
    shareButton.lastChild.style.fill = 'white';
}

Wow, that is a long function but don't worry, it does not do much. Most of those lines are just styling.

Firstly, we get the create the complete url by calling yet another function that we haven't defined, called getTweetURL, passing it the highlighted text, the extra text and the via handler.

We then define a list of styles on our shareButton to display it and position it appropriately.

The only important ones are the one relative to the positioning of the button, everything else is purely styling.

It may be gross to define each style on a different line like this but I figured it would be clearer for you to see. If you want, you can define styles this way too:

shareButton.style.cssText = `
/* your list of style here, same as how you would add it in a CSS file*/
`

You may have noticed this line: shareButton.innerHTML += tweetIcon;

We haven't defined yet a tweetIcon so let's go outside this function and copy this code:

 const tweetIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/></svg>`;

This is the tweet icon, it's a simple SVG I've found online, this will allow us to don't have to call it from a CDN or somewhere else.

Awesome, now we have a function to append the button to the DOM, we only need to define that function getTweetURL.

Let's do that now:

Construct the URL for the tweet

const getTweetURL = function (text, extra, via) {
    let url = 'https://twitter.com/intent/tweet?text=';
    // trim the text to fit in the max allowed 280 characters
    const viaUrl = `&via=${via}`;
    const maxLength = settings.maxLength > 280 ? 280 : settings.maxLength;
    const maxAllowedLength = maxLength - viaUrl.length - extra.length;
    let textToTweet = text;
    if(text.length > maxAllowedLength){
        textToTweet = text.substring(0,maxAllowedLength -1);
    }
    url += encodeURIComponent(textToTweet);
    if (extra)
        url += encodeURIComponent(' ' + extra);

    if (via)
        url += viaUrl

    return url;
    };

Let's break down this function:

  • first, we define the base URL that we need
  • then we create the portion of URL that contains our via handler
  • after that, we calculate how many characters in our text allowed to take, based on the maxLength we defined (or the max of 280), the via handler and the extra text
  • if the text is too long, we use substring to take only a portion of it
  • we then stick everything together and use encodeURIComponent to ensure all characters are escaped properly

There you have it, this function returns a perfect URL to share the tweet.

Now you can try this code on your webpage and you will see that everything should work fine.

If you want a more customizable plugin you can check out the one i've published on Github.


Thank you very much for reading. Follow me on DevTo or on Twitter for more.

complete guide to modern javascript alberto montalesi ebook bannerGet my ebook on Amazon and Leanpub or get my course on Educative


NEWEST ARTICLES




ABOUT ME

author alberto montalesi profile picture

Alberto is a software developer specialized in building enterpise software using Angular and author of the 'Complete guide to Modern JavaScript' ebook and course. In his free time he writes articles and tutorials on InspiredWebDev.com and Dev.to

You can read more about him here