«

»

Dec
27

Interactive Floor Plan with SVG, jQuery, JSON and WordPress

It started as a static image. I was provided with a PDF of an architectural diagram. Exhibitor spaces were being offered for an upcoming event. These numbered spaces would be filled in/grayed out as organizations reserved them. There is a corresponding table listing out the exhibitors and their corresponding spaces.

I ripped the PDF in Illustrator, maintaining the source .AI file, exporting to PNG, uploading it to the web server and editing the HTML table as edits came in. It occurred to me I could accomplish this in HTML5, perhaps using <canvas>, which would have probably required recreating the entire diagram programmatically in JavaScript. I considered that. It would be an interesting exercise, no doubt, though somewhat time consuming.

I opted to save the Illustrator file directly to SVG, using all the defaults. I examined the resulting file in my trusty text editor, pleasantly surprised at how human-readable the file was – albeit lengthy. Much of the document’s length was due to artifacts brought in during the PDF to Illustrator conversion. I also noted that entire sections of the XML document had id’s corresponding to layer names within the Illustrator file. So, I went back into Illustrator and cleaned up the organization of layers, naming them appropriately and then, in a fit of OCD, cleaned up all the graphic artifacts, which in fact amounted to recreating the entire diagram.

I did some reading up on <embed> and <object> tags and associated methods for embedded SVG, then opted, as I’ve been known to do, to live dangerously. I went ahead and copied the entire SVG object into an HTML page. This entailed copying everything after the DOCTYPE declaration and pasting it between the BODY tags. I fired it up in my browser and sure enough, there it was, the diagram, in all of its vector glory.

I played around with some jQuery to add a hover effect: mousing over <rect> objects triggers a change in fill color. Simple enough. I added a <div> container above the diagram to show the name of the exhibitors when the corresponding space is highlighted. I figured a little JSON would come in handy, so I pulled up the original table in my browser, copied the data and pasted it into Excel. By adding a couple of columns with commas, quotation marks and a colon, I was able to construct the notation, copy the range of cells, paste it into said trusty text editor, remove line breaks, enclose the whole she-bang in curly braces, copy and paste that into my <script> block and assign it to a variable, a quick-and-dirty associative array. With a little bit more jQuery DOM trickery, hovering now walks one step up the DOM to the parent element, in this case a <g> object (for “group,” which I find incredibly cool), then back down using jQuery’s find method to look for the text() contents of the <text> object, which is conveniently the number of the exhibitor space. jQuery then uses that as the key to call up the corresponding value and populate the <div> accordingly.

View the jQuery/Javascript/JSON code block

var strOriginalFill;
var targetRect;
var sourceText;
var exhibitorNamePlaceholder = "---";
var strHighlightFill = "#0ce640";
var arrExhibitors = {207:"Abbott",503:"Accenture",511:"Acurian",206:"Alexandria Real Estate",306:"Almac",402:"Barney & Barney",404:"BayBio",114:"Bend Research",305:"BIOCOM",411:"BioMed Realty Trust",606:"BioSpace",204:"BPM",701:"CNA",205:"Cooley",211:"Corning",107:"Deloitte",502:"DLA Piper",408:"Drinker Biddle",210:"Inc Research",505:"KPMG",102:"Kronos",310:"Latham & Watkins",602:"Morrison & Foerster",406:"Novartis",302:"PwC",104:"R&D Partners",507:"RoseRyan",303:"Squire Sanders",403:"VWR International",604:"Wareham Development",200:"Wells Fargo Insurance Services"};
jQuery.noConflict();
jQuery(document).ready(function($) {
	$("#exhibitor-spaces").children().css("cursor","pointer");
	$("#exhibitor-spaces").children("g").hover(
		function() {
				targetRect = $(this).find("rect");
				sourceText = $(this).find("text");
				strOriginalFill = targetRect.attr("fill");
				targetRect.attr("fill",strHighlightFill);
				$("#exhibitor-name").html(arrExhibitors[sourceText.text()]);
		},
		function() {
			targetRect.attr("fill",strOriginalFill);
			$("#exhibitor-name").html(exhibitorNamePlaceholder);
		}
	);
});

It worked famously. Now, I dropped it into a WordPress page. To my chagrin, it didn’t work quite as I had hoped. Sure, the JavaScript was inserted into the as planned courtesy of the Specific CSS/JS for Posts and Pages plugin. However, WordPress insisted on reformatting the SVG object. A little more reading yielded this article on disabling WordPress automatic formatting using a shortcode. I obediently added the PHP function into a new functions.php file in my child theme, then wrapped my <svg> object with the raw shortcode.

Add this code to your functions.php file

function my_formatter($content) {
	$new_content = '';
	$pattern_full = '{(\[raw\].*?\[/raw\])}is';
	$pattern_contents = '{\[raw\](.*?)\[/raw\]}is';
	$pieces = preg_split($pattern_full, $content, -1, PREG_SPLIT_DELIM_CAPTURE);

	foreach ($pieces as $piece) {
		if (preg_match($pattern_contents, $piece, $matches)) {
			$new_content .= $matches[1];
		} else {
			$new_content .= wptexturize(wpautop($piece));
		}
	}

	return $new_content;
}

remove_filter('the_content', 'wpautop');
remove_filter('the_content', 'wptexturize');

add_filter('the_content', 'my_formatter', 99);

The result is below. Roll over the grey numbered spaces to display organization names at the top. Bear in mind that not all spaces have names assigned. There are no <img> tags in this entire post!

Exhibitor:
711 709 707 705 703 701 610 608 606 604 602 511 510 509 508 507 506 505 504 503 502 500 411 410 409 408 407 406 405 404 403 402 401 400 311 310 309 308 307 306 305 304 303 302 301 300 211 210 209 208 207 206 205 204 203 202 201 200 114 112 111 110 109 108 107 106 105 104 103 102 101 100 Exit Exit Exit F&B F&B Exit Exit Exit Exit Exit Exit Exit Exit Exit Exit Exit Reserved for Event Sponsors No Longer Available

Leave a Reply