7 YEARS AGO

Tweaks: Copy web part

This tweak is similar to the "Widgetizer!" script and allows you to copy web parts from one page template to another.

This tweak is similar to the "Widgetizer!" script and allows you to copy web parts from one page template to another.

The screenshot below shows you the new "Copy to template" option. The option is available when you click on the little arrow next to a web part in the design mode of a document.

copy_to_template.png

The "Copy to template" button displays a list of page templates belonging to the current site. Selecting a page template will display the web part zones that are available for the page template:

copy_to_zone.png

If you click on a web part zone then the web part and it's properties will be copied to the selected page templates web part zone.

And that is pretty much all there is to it!

If you would like to add this tweak to your Kentico CMS installation then follow the steps below:

Step 1: Download the following file and place it in the App_Code folder (e.g. ~/App_Code/Global/Dude).

Step 2: Locate the file: WebPartMenu.ascx in ~/CMSModules/PortalEngine/Controls/WebParts and add the following code:

line 3 - 13:
<cms:ContextMenu runat="server" ID="menuCopyTo" MenuID="copyToMenu" VerticalPosition="Bottom"
    HorizontalPosition="Left" OffsetX="25" ActiveItemCssClass="ItemSelected" MenuLevel="1"
    ShowMenuOnMouseOver="true" MouseButton="Both" Dynamic="true">
    <asp:Panel runat="server" ID="pnlPageTemplates" CssClass="PortalContextMenu WebPartContextMenu">
        <asp:Repeater runat="server" ID="repPageTemplates">
            <ItemTemplate>
                <asp:Panel runat="server" ID="pnlPageTemplate" CssClass="Item" />
            </ItemTemplate>
        </asp:Repeater>
    </asp:Panel>
</cms:ContextMenu>
line 95 - 103:
<cms:ContextMenuContainer runat="server" ID="cmcCopyTo" MenuID="copyToMenu">
    <asp:Panel runat="server" ID="pnlCopyTo" CssClass="Item">
        <asp:Panel runat="server" ID="pnlCopyToPadding" CssClass="ItemPadding">
            <asp:Image runat="server" ID="imgCopyTo" CssClass="Icon" EnableViewState="false" />&nbsp;<asp:Label
                runat="server" ID="lblCopyTo" CssClass="NameInactive" EnableViewState="false"
                Text="CopyTo" />
        </asp:Panel>
    </asp:Panel>
</cms:ContextMenuContainer>
line 147 - 149:
function ContextCopyWebPartToPageTemplateZoneId(definition, targetPageTemplateId, zoneId) {
    CopyWebPart(definition[1], definition[3], targetPageTemplateId, zoneId);
}
Step 3: Open the code behind of WebPartMenu.ascx and adjust it as follows:

line 12:
using CMS.ExtendedControls;
line 20:
public partial class CMSModules_PortalEngine_Controls_WebParts_WebPartMenu : CMSAbstractPortalUserControl, IPostBackEventHandler
line 49 - 51:
// Copy web part
this.imgCopyTo.ImageUrl = GetImageUrl("CMSModules/CMS_PortalEngine/ContextMenu/Template.png");
this.lblCopyTo.Text = ResHelper.GetString("WebPartMenu.IconCopyTo", culture);
line 90 - 97:
// Build the list of page templates
DataSet dsPageTemplates = PageTemplateInfoProvider.GetAllowedTemplates(CMSContext.CurrentSiteID);
if (!DataHelper.DataSourceIsEmpty(dsPageTemplates))
{
    this.repPageTemplates.ItemDataBound += new RepeaterItemEventHandler(repPageTemplates_ItemDataBound);
    this.repPageTemplates.DataSource = dsPageTemplates;
    this.repPageTemplates.DataBind();               
}
line 101 - 169:
protected void repPageTemplates_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    // Get the page template panel
    Panel pnlPageTemplate = (Panel)e.Item.FindControl("pnlPageTemplate");
    if (pnlPageTemplate != null)
    {
        // Get the page template id from the dataitem
        int pageTemplateId = ValidationHelper.GetInteger(((DataRowView)e.Item.DataItem).Row["PageTemplateId"], 0);

        // Add the context menu container to the page template panel
        ContextMenuContainer cmcPageTemplate = new ContextMenuContainer();
        cmcPageTemplate.MenuID = String.Format("cmcPageTemplate{0}", e.Item.ItemIndex);
        pnlPageTemplate.Controls.Add(cmcPageTemplate);

        // Add the page template padding panel to the context menu container
        Panel pnlPageTemplatePadding = new Panel();
        pnlPageTemplatePadding.CssClass = "ItemPadding";
        cmcPageTemplate.Controls.Add(pnlPageTemplatePadding);

        // Add the page templates display name label to the page template padding panel
        Label lblPageTemplate = new Label();
        lblPageTemplate.CssClass = "Name";
        lblPageTemplate.Text = ValidationHelper.GetString(((DataRowView)e.Item.DataItem).Row["PageTemplateDisplayName"], String.Empty);
        pnlPageTemplatePadding.Controls.Add(lblPageTemplate);
         
        // Add the page template context menu to the page templates panel
        ContextMenu cmCopyToPageTemplate = new ContextMenu();
        cmCopyToPageTemplate.MenuID = String.Format("cmcPageTemplate{0}", e.Item.ItemIndex);
        cmCopyToPageTemplate.VerticalPosition = VerticalPositionEnum.Top;
        cmCopyToPageTemplate.HorizontalPosition = HorizontalPositionEnum.Left;
        cmCopyToPageTemplate.OffsetX = 25;
        cmCopyToPageTemplate.ActiveItemCssClass = "ItemSelected";
        cmCopyToPageTemplate.MenuLevel = 2;
        cmCopyToPageTemplate.ShowMenuOnMouseOver = true;
        cmCopyToPageTemplate.MouseButton = MouseButtonEnum.Both;
        pnlPageTemplates.Controls.Add(cmCopyToPageTemplate);

        // Add the web part zones panel to the page template context menu
        Panel pnlWebPartZones = new Panel();
        pnlWebPartZones.CssClass = "PortalContextMenu WebPartContextMenu";
        cmCopyToPageTemplate.Controls.Add(pnlWebPartZones);

        // Get the page template info
        PageTemplateInfo pageTemplateInfo = PageTemplateInfoProvider.GetPageTemplateInfo(pageTemplateId);
        if (pageTemplateInfo != null)
        {
            // Loop through the web part zones
            foreach (WebPartZoneInstance zone in pageTemplateInfo.WebPartZones)
            {
                // Add the web part zone panel to the web part zones panel
                Panel pnlWebPartZone = new Panel();
                pnlWebPartZone.Attributes.Add("onclick", "ContextCopyWebPartToPageTemplateZoneId(GetContextMenuParameter(\"webPartMenu\"), \"" + pageTemplateId + "\", \"" + zone.ZoneID + "\");");
                pnlWebPartZone.CssClass = "Item";
                pnlWebPartZones.Controls.Add(pnlWebPartZone);

                // Add the web part zone padding panel to the web part zone panel
                Panel pnlWebPartZonePadding = new Panel();
                pnlWebPartZonePadding.CssClass = "ItemPadding";
                pnlWebPartZone.Controls.Add(pnlWebPartZonePadding);

                // Add the web part zone label to the web part zone padding panel
                Label lblWebPartZone = new Label();
                lblWebPartZone.CssClass = "Name";
                lblWebPartZone.Text = zone.ZoneID;
                pnlWebPartZonePadding.Controls.Add(lblWebPartZone);
            }
        }                       
    }
}
line 171 - 185:
/// <summary>
/// PreRender event handler
/// </summary>
protected override void OnPreRender(EventArgs e)
{
    // Prepare the copy web part scripts

    string script = "function CopyWebPart(webPartId, instanceGuid, pageTemplateId, zoneId) {" +
                "setWebPart(webPartId); setGuid(instanceGuid); setTargetZone(pageTemplateId); setZone(zoneId);" +
                Page.ClientScript.GetPostBackEventReference(this, "CopyWebPart") +
            @"};";

    // Register the script
    ScriptHelper.RegisterClientScriptBlock(this, typeof(string), "CopyWebPart", ScriptHelper.GetScript(script));
}
line 187 - 208:
/// <summary>
/// RaisePostBack event handler
/// </summary>
/// <param name="eventArgument"></param>
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
    if ((eventArgument == null))
    {
        return;
    }

    if (PortalContext.ViewMode == ViewModeEnum.Design)
    {
        // Perform the action
        switch (eventArgument.ToLower())
        {
            case "copywebpart":
                CopyWebPart();
                break;
        }
    }
}
line 210 - 267:
private void CopyWebPart()
{
    string webPartControlId = String.Empty;
    Guid instanceGuid = Guid.Empty;
    int pageTemplateId = 0;
    string zoneId = String.Empty;

    // Get the web part control ID from the hiddenfield
    HiddenField hidSelectedWebPart = CMS.ExtendedControls.ControlsHelper.GetChildControl(Page, typeof(HiddenField), "hidSelectedWebPart") as HiddenField;
    if (hidSelectedWebPart != null)
    {
        webPartControlId = ValidationHelper.GetString(hidSelectedWebPart.Value, "");
    }

    // Get the instance guid from the hiddenfield
    HiddenField hidSelectedGuid = CMS.ExtendedControls.ControlsHelper.GetChildControl(Page, typeof(HiddenField), "hidSelectedGuid") as HiddenField;
    if (hidSelectedGuid != null)
    {
        instanceGuid = ValidationHelper.GetGuid(hidSelectedGuid.Value, Guid.Empty);
    }     

    // Get the page template id from the hiddenfield
    HiddenField hidTargetZone = CMS.ExtendedControls.ControlsHelper.GetChildControl(Page, typeof(HiddenField), "hidTargetZone") as HiddenField;
    if (hidTargetZone != null)
    {
        pageTemplateId = ValidationHelper.GetInteger(hidTargetZone.Value, 0);
    }

    // Get the selected zone ID from the hiddenfield
    HiddenField hidSelectedZone = CMS.ExtendedControls.ControlsHelper.GetChildControl(Page, typeof(HiddenField), "hidSelectedZone") as HiddenField;
    if (hidSelectedZone != null)
    {
        zoneId = ValidationHelper.GetString(hidSelectedZone.Value, "");
    }

    // Copy the web part
    if ((!String.IsNullOrEmpty(webPartControlId)) && (pageTemplateId > 0) && (!String.IsNullOrEmpty(zoneId)))
    {
        // Get source data
        PageInfo pi = CMSContext.CurrentPageInfo;
        if (pi != null)
        {
            // Get template instance
            PageTemplateInstance pti = DUDE.Widgetizer.GetTemplateInstanceForEditing(pi);
            if (pti != null)
            {
                // Get the web part instance
                WebPartInstance webPart = pti.GetWebPart(instanceGuid) ?? pti.GetWebPart(webPartControlId);

                // Get the page template info
                PageTemplateInfo pageTemplateInfo = PageTemplateInfoProvider.GetPageTemplateInfo(pageTemplateId);

                // Add the web part to the page templates zone
                pageTemplateInfo.AddWebPart(zoneId, webPart);
            }
        }
    }
}
Step 4: Add the following resource string:

Key: WebPartMenu.IconCopyTo
Text: Copy to template ...

Please note: this tweak is not fully tested and I cannot be liable for any defects or incompatibilities with Kentico CMS.
To do: create downloadable package for easy installation including integration with widgetizer