Skip to content

Dialog add copy link and open in a new tab buttons Copied From #2104

Victor Tomaili edited this page May 3, 2021 · 1 revision

This code and documentation was provided by @marcobisio I am simply adding it to the WIKI for others to easily find.

marcobisio >

In this simple guide I'll explain how to add two custom buttons in the ### dialog titlebar: "copy link" and "open in a new tab"

(see screenshot below).

Screen shot

Here we go:

  1. copy link button

1.1. add the following library to your project (and also include it in _LayoutHead.cshtml:):

https://clipboardjs.com

1.2. add the following typescript definition to your project:

declare namespace Clipboard {

    interface Options {
        /**
         * Overwrites default command ('cut' or 'copy').
         * @param {Element} elem Current element
         * @returns {String} Only 'cut' or 'copy'.
         */
        action?: (elem: Element) => string;

        /**
         * Overwrites default target input element.
         * @param {Element} elem Current element
         * @returns {Element} <input> element to use.
         */
        target?: (elem: Element) => Element;

        /**
         * Returns the explicit text to copy.
         * @param {Element} elem Current element
         * @returns {String} Text to be copied.
         */
        text?: (elem: Element) => string;
    }

    interface Event {
        action: string;
        text: string;
        trigger: Element;
        clearSelection(): void;
    }
}

declare class Clipboard {
    constructor(selector: (string | Element | NodeListOf<Element>), options?: Clipboard.Options);

    /**
     * Subscribes to events that indicate the result of a copy/cut operation.
     * @param type {String} Event type ('success' or 'error').
     * @param handler Callback function.
     */
    on(type: "success", handler: (e: Clipboard.Event) => void): this;
    on(type: "error", handler: (e: Clipboard.Event) => void): this;
    on(type: string, handler: (e: Clipboard.Event) => void): this;

    /**
     * Clears all event bindings.
     */
    destroy(): void;
}

declare var clipboard: Clipboard;

declare module "clipboard" {
    export = clipboard;
}

the defition above it's a slightly modified version of the Andrei Kurosh one.

1.3. declare the following global variable in your xyzDialog.ts:

protected titlebarCopyLinkButton: JQuery;

1.4. add the following code to the constructor of your xyzDialog.ts:

// clipboard vs jqueryui fix
$.ui.dialog.prototype._focusTabbable = $.noop;

// add copy link button
let buttonText = 'Copy link';
let spanCopyLink = $('<span></span>')
    //.addClass('ui-button-icon')
    .addClass('ui-icon')
    .addClass('ui-icon-link')
    .text(buttonText);

this.titlebarCopyLinkButton = $('<a></a>')
    .addClass('ui-dialog-titlebar-copy-link')
    .addClass('ui-corner-all')
    .addClass('ui-state-default')
    .attr('title', buttonText)
    .attr('href', '#')
    .attr('role', 'button')
    .appendTo(this.element.prev('.ui-dialog-titlebar').find('.ui-dialog-titlebar-buttonpane'));
spanCopyLink.appendTo(this.titlebarCopyLinkButton);

var clipboard = new Clipboard('.ui-dialog-titlebar-copy-link', {
    text: function (trigger) {
        return (trigger.hasAttribute('data-dialog-link') ? trigger.getAttribute('data-dialog-link') : '');
    }
});
clipboard.on('success', function (e) {
    Q.notifySuccess('Link copied to clipboard.');
    //console.info('Action:', e.action);
    //console.info('Text:', e.text);
    //console.info('Trigger:', e.trigger);
});
clipboard.on('error', function (e) {
    Q.notifyWarning('Unable to copy link to clipboard');
    //console.error('Action:', e.action);
    //console.error('Trigger:', e.trigger);
});

1.5. add the following method to your xyzDialog.ts:

private getDialogUrl(): string {
    return Q.resolveUrl('~/YOUR_MODULE/YOUR_ENTITY' + '#YOUR_MODULE-YOUR_ENTITY/' + this.entityId);
}

1.6. add the following code to the updateInterface() method of your xyzDialog.ts:

var titlebarCopyLinkAttribute = 'data-dialog-link';
this.titlebarCopyLinkButton.toggle(!this.isNew());
if (!this.titlebarCopyLinkButton.is('[' + titlebarCopyLinkAttribute + ']') && !this.isNew()) {
	this.titlebarCopyLinkButton.attr(titlebarCopyLinkAttribute, $(location).attr('protocol') 
                                        + '//' + $(location).attr('host') + this.getDialogUrl());
}

1.7. now we are able to copy a dialog link to the clipboard, but which is the point if we don't know how to use it? So add the following code in the constructor of your xyzGrid.ts in order to handle dialog links:

var locationHash = location.hash;
if (locationHash && locationHash != '' && locationHash != '#') {
    var locationHashArray: string[] = locationHash.split("/");
    var objType = locationHashArray[0].replace("#", "").replace("-", ".");
    var objId = locationHashArray[1];
    var dialogType: any = Serenity.DialogTypeRegistry.get(objType);
    var dialog = Serenity.Widget.create({
        type: dialogType
    });
    (dialog as Serenity.EntityDialog<any, any>).loadByIdAndOpenDialog(objId);
    // clean url hash param
    location.hash = "";
}

1.8. add the css class of the copy link button (site.xyz.less):

.ui-dialog-titlebar-buttonpane .ui-icon-link {
    background-image: url(../xyz/images/link_icon.png) !important;
    background-position: center center;
}
  1. open in a new tab button

2.1. declare the following global variable in your xyzDialog.ts:

protected titlebarOpenNewTabButton: JQuery;

2.1. add the following code to the constructor of your xyzDialog.ts:

// add open in a new tab button
let linkText = 'Open in a new tab';
let spanOpenNewTab = $('<span></span>')
    .addClass('ui-icon')
    .addClass('ui-icon-open-new-tab')
    .text(linkText);

this.titlebarOpenNewTabButton = $('<a></a>')
    .addClass('ui-dialog-titlebar-open-new-tab')
    .addClass('ui-corner-all')
    .addClass('ui-state-default')
    .attr('title', linkText)
    .attr('href', '#')
    .attr('role', 'button')
    .appendTo(this.element.prev('.ui-dialog-titlebar').find('.ui-dialog-titlebar-buttonpane'))
    .click(() => {
        window.open(this.getDialogUrl());
    });
spanOpenNewTab.appendTo(this.titlebarOpenNewTabButton);

2.2. add the following code to the updateInterface() method of your xyzDialog.ts:

this.titlebarOpenNewTabButton.toggle(!this.isNew());

2.3. add the css class of the open in a new tab button (site.xyz.less):

.ui-dialog-titlebar-buttonpane .ui-icon-open-new-tab {
    background-image: url(../xyz/images/externallink.png) !important;
    background-position: center center;
}
Clone this wiki locally