So if you remember back to when we set up the Overlay button on our new field, we updated the
Message
field to use "overlay". Let's handle this message in our ImageWithOverlay.cs class.///The overlay message. private const string OverlayMessage = "overlay"; ///The overlay application location. private const string OverlayAppLocation = "/sitecore/client/Your Apps/OverlaySelector"; public override void HandleMessage(Message message) { if (message["id"] != ID) { return; } string[] command = message.Name.Split(':'); Assert.IsTrue(command.Length > 1, "Expected message format is control:message"); if (command[1] == OverlayMessage) { Sitecore.Context.ClientPage.Start(this, "Overlay"); return; } base.HandleMessage(message); } public void Overlay(ClientPipelineArgs args) { if (args.IsPostBack) { if (!args.HasResult) { return; } XmlValue.SetAttribute(Models.Constants.CoordinatesAttribute, args.Result); Update(); SetModified(); SheerResponse.Refresh(this); } else { UrlString urlString = new UrlString(OverlayAppLocation); Item selectedImage = GetMediaItem(); if (selectedImage != null) { urlString["fo"] = selectedImage.Uri.ToString(); } string coords = XmlValue.GetAttribute(Models.Constants.CoordinatesAttribute); if (!string.IsNullOrEmpty(coords)) { urlString["coords"] = coords; } SheerResponse.ShowModalDialog(new ModalDialogOptions(urlString.ToString()) { Width = "800px", Height = "275px", Response = true, ForceDialogSize = true }); args.WaitForPostBack(); } }
This code handles the message and will open our SPEAK application that we're about to make. We're passing the existing coordinates (if they're set) and the Uri of the main image (so that we can display it in our SPEAK dialog).
Ok let's build our SPEAK app. This will show our main image with our overlay image over top, and allow the user to drag the overlay around to set its coordinates. It'll also have a 'save' and 'cancel' button which sets (or not) the coordinates on the main image field.
In Sitecore Explorer, expand core/sitecore/client/Your Apps. Right click it and create a
/sitecore/client/Business Component Library/Templates/Pages/Speak-DialogPage
called "OverlaySelector". Set the following properties:- Theme: Oxford
- Subthemes: Dialogs
Open the design layout (right click -> tasks -> Design Layout, or Ctrl+U) and set
- Layout: /sitecore/client/Speak/Layouts/Layouts/Speak-Layout
Add the following renderings:
Type | ID | Location | Other | |
---|---|---|---|---|
PageCode | Page.Code | PageCodeScriptFileName: /Scripts/Speak/Overlay.js | ||
Dialog | Page.Body | |||
DialogHeader | DialogHeader | |||
DialogFooter | DialogFooter | |||
DialogContentM | DialogContent | |||
Text | HeaderTitle | DialogHeader.Title | Text: Select a teardrop position | |
Section | MainImage | DialogContent.Main | ||
Image | OverlayImage | MainImage.Content | Alt: Overlay, Height: 300, Width: 245, ImageUrl: /Content/Images/overlay.png | |
Text | Coordinates | DialogContent.Main | Text: 100,100 | |
Button | SaveButton | DialogFooter.Button | ButtonType: Primary, Text: Select | |
Button | CancelButton | DialogFooter.Button | ButtonType: Primary, Text: Cancel | |
Rule | SaveButtonRule | Page.Body | Field: Rule, RuleItemId: (see below), TargetControl: SaveButton, Trigger: click | |
Rule | CancelButtonRule | Page.Body | Field: Rule, RuleItemId: (see below), TargetControl: CancelButton, Trigger: click |
/sitecore/cilent/Speak/Templates/Pages/PageSettings
item which will have the settings for our dialog (for now, just the 2 rules for our buttons).Under the PageSettings item, create:
/sitecore/client/Speak/Layouts/Renderings/Resources/Rule Definition
called CancelButtonRuleDefinition with rule: where always close the dialog/sitecore/client/Speak/Layouts/Renderings/Resources/Rule Definition
called SaveButtonRuleDefinition with rule: where always the dialog return value to component Coordinates textThe final step is to add our javascript for the component. We'll use jQuery UI to make the overlay draggable.
define(["sitecore", "jquery", "jqueryui"], function (_sc, $, ui) { var overlaySelectorDialog = _sc.Definitions.App.extend({ initialized: function () { var app = this; var scale = 1; var itemUriString = _sc.Helpers.url.getQueryParameters(window.location.href)['fo']; var itemPath = null; try { var itemUri = new URL(itemUriString); itemPath = itemUri.pathname; if (itemPath == "" || itemPath.indexOf("?") > -1) throw "Invalid URL"; } catch (e) { // Doesn't support URL (IE and pretty much FF as well) var slashes = itemUriString.indexOf("//"); var query = itemUriString.indexOf("?"); if (slashes > -1) itemPath = itemUriString.substring(slashes, query > -1 ? query : itemUriString.length); } var mainImage = document.querySelector('[data-sc-id="MainImage"]'); if (itemPath == null || itemPath == "") { alert("Couldn't parse item URL for your background image"); } else { var itemUriSplit = itemPath.substring(2).split("/"); var database = new _sc.Definitions.Data.Database(new _sc.Definitions.Data.DatabaseUri(itemUriSplit[0])); database.getItem(itemUriSplit[1], function (item) { if (item == null) alert("Couldn't find background image item in database for unknown reason"); else { var imgWidth = parseInt(item.Width); var imgHeight = parseInt(item.Height); if (imgWidth > imgHeight) { scale = 500 / imgWidth; mainImage.style.height = Math.round(scale * imgHeight) + "px"; } else { scale = 500 / imgHeight; mainImage.style.width = Math.round(scale * imgWidth) + "px"; } mainImage.style.backgroundImage = "url('" + item.$mediaurl.replace("thn=1", "") + "&w=500')"; var coords = _sc.Helpers.url.getQueryParameters(window.location.href)['coords']; if (coords != null && coords != "") { app.Coordinates.set('text', coords); var coordsSplit = coords.split(","); jQuery('[data-sc-id="OverlayImage"]').css({ "left": (parseInt(coordsSplit[0]) * scale) + "px", "top": (parseInt(coordsSplit[1]) * scale) + "px" }); } } }); } mainImage.style.height = "500px"; mainImage.style.width = "500px"; mainImage.style.backgroundSize = "cover"; jQuery('[data-sc-id="OverlayImage"]').draggable({ containment: '[data-sc-id="MainImage"]', scroll: false, start: function (e, ui) { app.Coordinates.set('text', Math.round(ui.position.left / scale) + "," + Math.round(ui.position.top / scale)); }, drag: function (e, ui) { app.Coordinates.set('text', Math.round(ui.position.left / scale) + "," + Math.round(ui.position.top / scale)); }, stop: function (e, ui) { app.Coordinates.set('text', Math.round(ui.position.left / scale) + "," + Math.round(ui.position.top / scale)); } }); } }); return overlaySelectorDialog; });I've uploaded the full code to Github if you'd like to try it out for yourself.
No comments:
Post a Comment