JavaScript: creare un widget per la condivisione sui social network

JavaScript: creare un widget per la condivisione sui social network

In questo articolo vedremo come creare un widget per i pulsanti social utilizzando JavaScript senza dipendenze e con i CSS.

Un pulsante di condivisione ha parti fisse e variabili. Le parti fisse sono gli stili CSS, l'eventuale icona e l'URL di base di condivisione del sociala network mentre le parti variabili sono l'URL da condividere e l'eventuale descrizione.

Un widget può essere rappresentato come una classe JavaScript che avrà metodi e proprietà. Il widget dovrà essere configurabile, quindi al costruttore della classe passeremo un oggetto letterale con le varie opzioni.

Nelle opzioni definiremo:

  1. L'ID del contenitore.
  2. Il percorso al foglio di stile principale.
  3. Il percorso al foglio di stile del web font delle icone.
  4. Un array iniziale di pulsanti.
  5. L'elemento genitore del contenitore.
  6. Un flag booleano che indica se il widget deve essere nascosto per i dispositivi mobile.
  7. La posizione sullo schermo del widget.
  8. Il layout del widget (verticale o orizzontale).

Le nostre opzioni verranno definite come segue:

const defaults = {
                cssIconsPath: 'css/fontawesome/css/all.css',
                cssPath: 'css/social-share.css',
                hideOnMobile: true,
                elementID: 'social-share',
                parentElement: document.body,
                buttons: [
                    {
                        name: 'Facebook',
                        icon: 'fab fa-facebook-f',
                        cssClass: 'social-share-facebook',
                        url: location.href,
                        text: '',
                        shareURL: 'https://www.facebook.com/sharer.php?u={url}',
                        styles: null
                    }
                ],
                position: 'left',
                display: 'vertical'
            };

            this.options = Object.assign(defaults, options);

Ciascun pulsante è un oggetto che ha un nome, una classe CSS per l'icona, una classe CSS per il link stesso, l'URL da condividere, il testo da condividere, l'URL di base del social network e un oggetto facoltativo con cui aggiungere degli stili CSS inline al pulsante.

I CSS principali vengono inseriti creando un elemento style prima del contenitore principali in cui verranno aggiunte due direttive CSS @import.

addStyles(target) {
            const baseURL = location.protocol + '//' + location.host + '/';
            const iconsURL = baseURL + this.options.cssIconsPath;
            const cssURL = baseURL + this.options.cssPath;

            this.styleElement = document.createElement('style');
            this.styleElement.id = this.options.elementID + '-css';
            this.styleElement.innerText = `@import url(${iconsURL}); @import url(${cssURL});`;

            target.before(this.styleElement);
        }

Per evitare problemi con percorsi relativi è sempre bene usare URL assoluti. Il metodo che crea il widget è il seguente:

create() {
            this.element = document.createElement('ul');
            this.element.id = this.options.elementID;
            this.options.parentElement.appendChild(this.element);

            this.element.classList.add(this.options.position);
            this.element.classList.add(this.options.display);
            this.addStyles(this.element);
            this.addButtons();

            if(this.options.hideOnMobile) {
                if(/mobile/gi.test(navigator.userAgent)) {
                    this.element.style.display = 'none';
                }
            }
        }

Gli stili CSS predefiniti sono i seguenti:

#social-share {
    margin: 0;
    padding: 0;
    list-style: none;
    width: 40px;
    position: fixed;
    z-index: 9999;
}

#social-share.horizontal {
    width: auto;
    position: static;
    z-index: initial;
    display: flex;
    flex-wrap: wrap;
}

#social-share.left {
    top: 50%;
    left: 0;
    transform: translateY(-50%);
}

#social-share.right {
    top: 50%;
    right: 0;
    transform: translateY(-50%);
}

#social-share.top {
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: auto;
    display: flex;
    flex-wrap: wrap;
}

#social-share.bottom {
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: auto;
    display: flex;
    flex-wrap: wrap;
}

#social-share li {
    display: block;
}

#social-share a {
    display: block;
    text-decoration: none;
    color: #fff;
    width: 40px;
    height: 40px;
    line-height: 40px;
    text-align: center;
}

#social-share a[class*=facebook] {
    background:#3a579a;
}

#social-share a[class*=twitter] {
    background:#00abf0;
}
#social-share a[class*=linkedin] {
    background:#127bb6;
}

Il metodo più complesso della nostra classe è sicuramente quello che inserisce i pulsanti nella lista. Effettua un loop sull'array options.buttons e crea le varie voci della lista in questo modo:

addButtons() {
            if (Array.isArray(this.options.buttons) && this.options.buttons.length > 0) {
                this.options.buttons.forEach(button => {
                    let item = document.createElement('li');
                    let link = document.createElement('a');

                    link.className = button.cssClass;
                    link.title = button.name;
                    link.href = button.text.length > 0 ?
                        button.shareURL.replace('{url}', button.url).replace('{text}', encodeURIComponent(button.text))
                        : button.shareURL.replace('{url}', button.url);
                    link.innerHTML = `<i class="${button.icon}"></i>`;

                    if(button.styles !== null) {
                        for(let prop in button.styles) {
                            link.style[prop] = button.styles[prop];
                        }
                    }

                    link.addEventListener('click', e => {
                        e.preventDefault();
                        let url = link.href;
                        let width = 550;
                        let height = 450;
                        let left = (screen.width - width) / 2;
                        let top = (screen.height - height) / 2;

                        let newWindow = window.open(url, '', 'scrollbars=1, width=' + width + ', height=' + height + ', left=' + left + ', top=' + top);

                        if (newWindow.focus) {
                            newWindow.focus();
                        }
                    }, false);

                    item.appendChild(link);
                    this.element.appendChild(item);
                });
            }
        }

Al click su ciascun pulsante si aprirà una finestra modale che riporterà alla pagina del social network per la condivisione della risorsa. Se la proprietà styles è un oggetto, verranno aggiunti degli stili inline al pulsante in base alle proprietà di stile contenute nell'oggetto.

Dobbiamo anche prevedere gli aggiornamenti al layout del nostro widget, come ad esempio la modifica di un'opzione o l'aggiunta di un nuovo pulsante. Creiamo quindi un metodo che rigenera il nostro widget.

redraw() {
            this.element.remove();
            this.styleElement.remove();
            this.create();
        }

Quindi possiamo creare un metodo per aggiungere un nuovo pulsante:

addButton(button) {
            this.options.buttons.push(button);
            this.redraw();
        }

E un metodo per aggiornare un'opzione:

setOption(name, value) {
            if(name in this.options) {
                this.options[name] = value;
                this.redraw();
            }
        }

Il test finale è semplice:

'use strict';

const socialShare = new SocialShare({
    cssIconsPath: 'demo/javascript-social-share/css/fontawesome/css/all.css',
    cssPath: 'demo/javascript-social-share/css/social-share.css'
});

const demoSelect = document.querySelector('#position');
const demoAddBtn = document.querySelector('#add-button');

demoSelect.addEventListener('change', () => {
    let position = demoSelect.options[demoSelect.selectedIndex].value;
    socialShare.setOption('position', position);
}, false);

demoAddBtn.addEventListener('click', e => {
    e.preventDefault();
    const newSocialButton = {
        name: 'Pinterest',
        icon: 'fab fa-pinterest-p',
        cssClass: 'social-share-pinterest',
        url: location.href,
        text: document.title,
        shareURL: 'https://pinterest.com/pin/create/button/?url={url}&description={text}',
        styles: {
            backgroundColor: '#cd1c1f'
        }
    };
    socialShare.addButton(newSocialButton);
}, false);

Demo

JavaScript Social Share

Torna su