Custom Url Coordinate Picker

In a previous post, I shared an SDL Tridion Custom Url Color Picker (pop-up) extension that read and set values from a single Component field.

This X & Y Coordinate Picker extends the concept to read and set values from multiple fields. Use these patterns in combination with your favorite JQuery or server-side controls to quickly create author-friendly interfaces for nearly any pop-up interface you could design. For other examples see:

Let’s see how the markup and script work together to make selecting X & Y coordinates in an image easier.

Custom Url Markup – CoordinatePicker.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<link rel="stylesheet" type="text/css" href="CoordinatePicker.css" />
    <script type="text/javascript" src="jquery-2.1.1.js"></script>
    <script type="text/javascript" language="javascript" src="/WebUI/Core/Controls/Popup/PopupInit.js"></script>
	<script type="text/javascript" language="javascript" src="CoordinatePicker.js"></script>
	<title>CreateAndBreak CoordinatePicker </title>
</head>

<body>
	<h2>Click on the image to pick a Coordinate</h2>
	<div>
		<img src="" id="image"></img>
	</div>
	<div>
		<input type="text" id="X"/><input type="text" id="Y"/>
	</div>
	<button type="button" id="save">Save Coordinates</button>
	<button type="button" id="cancel">Cancel</button>
	<div>
	<a href="http://createandbreak.net?source=coordinatepicker" title="Alvin's Blog" target="_blank"><img alt="Visit Alvin's Blog for more Tridion Information" class="logo" src="https://lh4.googleusercontent.com/-TEM87xavD3Q/TtHTujXUXsI/AAAAAAAAIg0/SyYru2BX3BM/s144/CreateAndBreak.png"></a></div>
</body>

</html>

tridion-coordinate-picker-custom-pop-up

Use the CSS (CoordinatePicker.css) to control the pop-ups look-and-feel.

#image {
    border: 1px solid #dfdfdf;
}

.logo {
    padding: 0.25em;
    float: right;
}

body {
    background: #f3ece2;
}

Script

The script loads a linked image from the Component form into the pop-up as well as reads/sets X & Y coordinates. Authors just need to click on the Component’s Image field description to present the pop-up with image and values loaded. After clicking on the image, they can save the values back to the Component form.

// assumes XML content structure of:
/* <Content xmlns="namespace">
	<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="tcm:1-123"></image>
	<X>3.14</X>
	<Y>42</Y>
   </Content>
*/

// Thanks to the Tridion Cookbook authors for $diplay examples
// https://code.google.com/p/tridion-practice/wiki/AnguillaSnippets

var args =  window.dialogArguments;
var X, Y;
var img;
var imgPath;
var labelX, labelY;

$(document).ready(function() {

// CustomUrl pop-up client-side selections
	labelX = $("#X");
	labelY = $("#Y");

	if (args) {
		var fields = args.getFields();
		if (fields && fields.length > 0) {
			img = args.getFields()[0].getValues();
			if (img != null) { // set image if already linked in the Component
				$('#image').attr("src", "/WebUI/Editors/CME/icon.png?uri=" + img);
			}
		}		

		// controller is $display
		var fb = args.controller.getView().properties.controls.fieldBuilder;
		//if metadata: $display.getView().getMetadataTab().properties.controls.fieldBuilder

		X = fb.getField("X").getValues();
		Y = fb.getField("Y").getValues();		

		labelX.val(X);
		labelY.val(Y);
	}

	(function (window, $, undefined) {

		$("#image").click(function(e) {

		var offset = $(this).offset();
		var relativeX = (e.pageX - offset.left);
		var relativeY = (e.pageY - offset.top);

		var XPercent = (relativeX / $(this).width() * 100 );
		var YPercent = (relativeY / $(this).height() * 100);

		labelX.val(XPercent.toFixed(1).toString());
		labelY.val(YPercent.toFixed(1).toString());
	});

})(window, jQuery);

$(":button#save").click(function() {
	var args = window.dialogArguments;
	if (args) {
		var fields = args.getFields();

		var fb = args.controller.getView().properties.controls.fieldBuilder;

		fb.getField("X").setValues([labelX.val()]);
		fb.getField("Y").setValues([labelY.val()]);

	}
		window.close();
});

$(":button#cancel").click(function(e) {
	e.preventDefault();
	window.close();
});

});

tridion-coordinate-picker-component-form-view

tridion-coordinate-picker-schema-design

Find the cource code in the “Picker” SVN directory of the Tridion World Google Code Repository released under an RPL license. Feedback appreciated in the comments but for general help with Custom Urls consider asking on Tridion Stack Exchange.

For an even more in-context authoring interface, consider applying these approaches to the Tridion Behavior Injection (FBI) extension.

As with any content modeling pattern, take care not to abuse such an approach. I’ve seen Tridion customers use coordinates for functionality like:

  • Prices on product offers
  • “Pop-up” details that describe scenes

Use Sparingly

With visitors experiencing websites on more devices, across varying resolutions, and in yet-to-be-discovered contexts, you probably don’t want to rely too much on pixels. X & Y coordinates and this extension are probably best fitted for positioning “labels” on an image, preferably based on percents and limited to certain contexts. In other words, consider how your image, scene, or experience looks on very small or very large screens.

In terms of practicality, for promotional content types that only have one destination, skip pixel-perfect precision and make template the clickable area. Pixel-level control offers flexibility, but it can take away from solutions that scale across devices and ultimate flexibility has an ultimate cost on your ability to manage customer experiences.

No time for an extension? There are quick-and-dirty ways to easily determine coordinates for an image.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>