1
\$\begingroup\$

I'm trying to create bootstrap plugin that will be used for copying content to clipboard.

I managed to build working version of my plugin but I'm wondering how I can improve it.

Idea is to show a small popover with two options: one will allow copying button content and second prepared link:

enter image description here

Below is my code:

/* ========================================================================
 * Bootstrap: popmenu.js v0.0.1
 * ======================================================================== */
+ function($) {
    'use strict';

    if (!$.fn.popover) throw new Error('Popmenu requires popover.js');
    if (!window.ZeroClipboard) throw new Error('Popmenu requires ZeroClipboard.js');

    // POPMENU PUBLIC CLASS DEFINITION
    // ===============================

    var Popmenu = function(element, options) {
        this.init('popmenu', element, options);
        this.addTooltip();
        this.$element.on('shown.bs.' + this.type, this.options.selector, $.proxy(this.createZero, this));

        ZeroClipboard.config({
            hoverClass: "hover",
            activeClass: 'active',
            forceHandCursor: true
        });
    };

    Popmenu.VERSION = '0.0.1';

    Popmenu.DEFAULTS = $.extend({}, $.fn.popover.Constructor.DEFAULTS, {
        html: true,
        trigger: 'focus',
        content: '<div class="btn-group">' +
            '<a href="#" role="button" class="btn btn-default copy  tooltipped tooltipped-n" aria-label="Link"><span class="fa fa-link"></span></a>' +
            '<a href="#" role="button" class="btn btn-default copy number tooltipped tooltipped-n" aria-label="Numer"><span class="fa fa-copy"></span></a>' +
            '</div>',
        title: '',
        container: 'body',
        placement: 'top',
        template: '<div class="popover" role="tooltip"><div class="arrow"></div><div class="popover-content no-padding"></div></div>',
        tooltip: 'Click for actions',
        tooltipPosition: 'e',
        url: window.location.protocol + '//' + window.location.host + '/'
    });


    // NOTE: POPMENU EXTENDS popover.js
    // ================================

    Popmenu.prototype = $.extend({}, $.fn.popover.Constructor.prototype);

    Popmenu.prototype.constructor = Popmenu;

    Popmenu.prototype.getDefaults = function() {
        return Popmenu.DEFAULTS;
    };

    Popmenu.prototype.addTooltip = function() {
        var $e = this.$element;
        var o = this.options;

        if (this.options.tooltip) {
            var t = typeof o.tooltip == 'function' ? o.tooltip.call($e[0]) : o.tooltip;
            var tp = typeof o.tooltipPosition == 'function' ? o.tooltipPosition.call($e[0]) : o.tooltipPosition;
            $e.attr('aria-label', t).addClass('tooltipped tooltipped-' + tp);
        }
    };

    Popmenu.prototype.createZero = function(e) {
        var self = this;
        var t = e.currentTarget.text;
        var args;
        var clip = new ZeroClipboard($(".copy"));
        clip.on("copy", function(event) {
            var clipboard = event.clipboardData;
            var data = "";
            if ($(event.target).hasClass("number")) {
                data = t;
                args = {
                    type: 'number',
                    data: data
                };
            } else {
                data = self.options.url + t;
                args = {
                    type: 'link',
                    data: data
                };
            }
            clipboard.setData("text/plain", data);
            self.$element.trigger('copied.bs.' + self.type, args);
            ZeroClipboard.deactivate();
        });
    };

    // POPMENU PLUGIN DEFINITION
    // =========================

    function Plugin(option) {
        return this.each(function() {
            var $this = $(this);
            var data = $this.data('bs.popmenu');
            var options = typeof option == 'object' && option;
            var selector = options && options.selector;

            if (!data && option == 'destroy') return;
            if (selector) {
                if (!data) $this.data('bs.popmenu', (data = {}));
                if (!data[selector]) data[selector] = new Popmenu(this, options);
            } else {
                if (!data) $this.data('bs.popmenu', (data = new Popmenu(this, options)));
            }
            if (typeof option == 'string') data[option]();
        });
    }

    var old = $.fn.popmenu;

    $.fn.popmenu = Plugin;
    $.fn.popmenu.Constructor = Popmenu;


    // POPMENU NO CONFLICT
    // ===================

    $.fn.popmenu.noConflict = function() {
        $.fn.popmenu = old;
        return this;
    };

    // POPMENU AUTO INIT
    // ===================
    //$(function(){$("[data-popmenu]").popmenu()})

}(jQuery);

What I'm most concern about:

  1. Is ZeroClipboard initialized in right place? I think that right now I'm creating instance every time popover is shown. Can I create it only once?
  2. Right now I assume that ZeroClipboard swf will load and work correctly. How should/can I disable my plugin is swf won't work? Plugin should work only if ZeroClipboard won't have any errors.
  3. How should I access buttons in my popover? Right now I'm selecting by class (copy), this is doe for whole page. Probably this is another place for improvements.
  4. Because this in my first bootstrap plugin any tips how to improve it in general are welcome.
\$\endgroup\$
  • \$\begingroup\$ This is a jQuery plugin, yes? \$\endgroup\$ – ArtOfCode Jan 5 '15 at 18:01
  • \$\begingroup\$ @ArtOfCode Yes, this is a jQuery plugin, it extends bootstrap popover. \$\endgroup\$ – Misiu Jan 5 '15 at 19:36
  • \$\begingroup\$ You might want to consider using jQuery's recommended method of structuring, then. Have a look at jquery.com for details \$\endgroup\$ – ArtOfCode Jan 5 '15 at 19:37
  • \$\begingroup\$ @ArtOfCode I'm extending popover just as it is extending tooltip. This is right way in my opinion, I need a way to optimize ZeroClipboard usage \$\endgroup\$ – Misiu Jan 5 '15 at 20:24
  • 1
    \$\begingroup\$ Fair enough, it was just a suggestion \$\endgroup\$ – ArtOfCode Jan 5 '15 at 20:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.