Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <html>
<head>
	<title>SVG tspan justification with meta-art</title>
</head>
<body>
	<div id="main">
		<div id="original-template">
			<h2>Template: Narwhal Business Cards</h2>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 216 108" enable-background="new 0 0 216 108" xml:space="preserve">
<g id="shell">
	
		<image overflow="visible" width="1200" height="750" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABLAAAALuCAYAAAC+de9yAAAACXBIWXMAAC4jAAAuIwF4pT92AAAA
GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAJ1FJREFUeNrs3c9r3Gee4PGvpJLk
aBEtx+7I1thGpt1E6WaDDbvgkBySXBZdJviwhxy2YY5z7L9kWPqQy0JDQ+jbZPfkpQ9xFro7YRiI
N0s6CniQNum1rawdK2jWtn6UtP58YyWyflmW66n6VNXrRRflVqAkPVUlqDfP8/lWFQAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
+tnOEkD3iRgjZD3lj5twBQAA0Duf8SwBdK+dIat5b66vZ2T9cFTw5EXhCgAAoIcIWNADtkLW5tmH
9W6stW8+7qurFsbVBCNcDU3MmHEFAADQgwQs6CHf70C6XN+aywvV+t1Pe3ZXVvyusdOqceJSHbAA
AADoXQIW9Kih8en6Vj363/rd69X6vS+qjeWFro5ZEa2Gjs9UjYlX6t1WAAAA9AcBC/rhjX7iYn0L
zaW5qrk8X60/uu+GY4axuypCnJ1WAAAAffy51hJAf4mdS3EbOTtbba4u1UcNN+7fenx/u/M/3/j0
42h1vhp89G8zrQAAABCwoI/F8Pd6Z9bj3VkhQlaErdidFTu14shhibBVH2+MI4Fjp+tgFT+LHVYA
AADsRcACnlCHpceGqzef+G8Rt77/x7NFrcFtj7n98QEAAOAwBCzg0LbHJ0PUAQAAaJdBSwAAAABA
ZgIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAA
QGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAA
AEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUA
AABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAF
AAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqA
BQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCa
gAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQ
moAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAA
kJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAA
AJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEA
AACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmAB
AAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZg
AQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQm
YAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACk
JmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAA
pCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAA
AKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAA
AACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgA
AAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlY
AAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJ
WAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACp
CVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAA
qQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAA
AKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAA
AACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYA
AAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIW
AAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoC
FgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBq
AhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABA
agIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAAAEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAA
QGoCFgAAAACpCVgAAAAApCZgAQAAAJCagAUAAABAagIWAAAAAKkJWAAAAACkJmABAAAAkJqABQAA
AEBqAhYAAAAAqQlYAAAAAKQmYAEAAACQmoAFAAAAQGoCFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAD8f/bggAAAAABAyP/XDQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAsJAAAwAc2xeGlrZlpAAAAABJRU5ErkJggg==" transform="matrix(0.24 0 0 0.24 -36 -36)">
	</image>
</g>
<g id="text">
	<g id="full-name">
		<text transform="matrix(1 0 0 1 75.2238 44.2869)" fill="#551D00" font-family="'Helvetica'" font-size="10px">{{ first_name + &quot; &quot; + last_name}}</text>
		<rect id="full-name--j-c" x="83.677" y="35.701" fill="none" width="124.704" height="13.396"/>
	</g>
	<g id="title">
		<text transform="matrix(1 0 0 1 133.9718 53.7566)" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ title }}</text>
		<rect id="title--j-c" x="85.518" y="47.746" fill="none" width="121.029" height="9.377"/>
	</g>
	<g id="contact-block">
		<text transform="matrix(1 0 0 1 116.6367 75.3995)"><tspan x="0" y="0" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ &quot;Office: &quot; + office_phone }}</tspan><tspan x="37.365" y="8.4" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ &quot;Fax: &quot; + fax }}</tspan><tspan x="-6.228" y="16.8" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ &quot;Mobile: &quot; + mobile_phone }}</tspan><tspan x="-6.986" y="25.2" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ &quot;E-mail: &quot; + email_address }}</tspan></text>
		<rect id="contact-block--j-r" x="109.497" y="69.389" fill="none" width="95.73" height="34.578"/>
	</g>
	<g id="address-block">
		<text transform="matrix(1 0 0 1 9.8296 75.3996)"><tspan x="0" y="0" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ line_1 }}</tspan><tspan x="0" y="8.4" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ line_2 }}</tspan><tspan x="0" y="16.8" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ line_3 }}</tspan><tspan x="0" y="25.2" fill="#551D00" font-family="'Helvetica'" font-size="7px">{{ line_4 }}</tspan></text>
		<rect id="address-block--j-l" x="9.676" y="69.389" fill="none" width="93.713" height="34.578"/>
	</g>
</g>
</svg>

		</div>
		<div id="user-input">
			<form>
				<fieldset>
					<legend>Name &amp; Title</legend>
					<div class="field-entry"><label for="first-name">First Name:</label><input placeholder="" v-model="first_name" name="first-name" id="first-name" type="text"></div>
					<div class="field-entry"><label for="last-name">Last Name:</label><input placeholder="" v-model="last_name" name="last-name" id="last-name" type="text"></div>
					<div class="field-entry"><label for="title">Title:</label><input placeholder="" v-model="title" name="title" id="title" type="text"></div>
				</fieldset>
				<fieldset>
					<legend>Contact Information</legend>
					<div class="field-entry"><label for="office-phone">Office:</label><input placeholder="" v-model="office_phone" name="office-phone" id="office-phone" type="text"></div>
					<div class="field-entry"><label for="fax">Fax:</label><input placeholder="" v-model="fax" name="fax" id="fax" type="text"></div>
					<div class="field-entry"><label for="mobile-phone">Mobile:</label><input placeholder="" v-model="mobile_phone" name="mobile-phone" id="mobile-phone" type="text"></div>
					<div class="field-entry"><label for="email-address">Email:</label><input placeholder="" v-model="email_address" name="email-address" id="email-address" type="text"></div>
				</fieldset>
				<fieldset>
					<legend>Company Address</legend>
					<div class="field-entry"><label for="line-1">Line 1:</label><input placeholder="" v-model="line_1" name="line-1" id="line-1" type="text"></div>
					<div class="field-entry"><label for="line-2">Line 2:</label><input placeholder="" v-model="line_2" name="line-2" id="line-2" type="text"></div>
					<div class="field-entry"><label for="line-3">Line 3:</label><input placeholder="" v-model="line_3" name="line-3" id="line-3" type="text"></div>
					<div class="field-entry"><label for="line-4">Line 4:</label><input placeholder="" v-model="line_4" name="line-4" id="line-4" type="text"></div>
				</fieldset>
				<button id="user-submit">Submit</button>
			</form>
		</div>
	</div>
	<script src="svg.js"></script>
	<script src="script.js"></script>
</body>
</html>
              
            
!

CSS

              
                body {
	font-family: Helvetica, Aria, sans-serif;
	background-color: #678;
}
#main {
	padding-top: 10px;
}
#original-template, #user-input {
	max-width: 400px;
	margin: auto;
	margin-bottom: 0.5em;
	padding: 10px;
  border: 1px solid #CCC;
  border-radius: 6px;
  background: #FFF;
  box-shadow: 0 3px 10px rgba(0,0,0,0.15);
}
#original-template h2 {
	margin: auto;
	margin-bottom: 0.75em;
	font-size: 1.15em;
	text-align: center;
}
#user-input label {
  margin-right: 5px;
  width: 85px;
  display: inline-block;
  text-align: right;
}
.field-entry {
  margin-bottom: 3px;
}
.field-entry input {
  width: 270px;
}
fieldset {
	margin-bottom: 5px;
}
#user-input button {
  width: 100%;
  border: 1px solid #AAA;
  display: inline-block;
  padding: 5px;
  font-size: 1em;
  margin-top: 5px;
  background-color: #EFEFEF;
  cursor: pointer;
}
@media only screen and (max-height : 500px){
  #user-input {
    height : 120px;
    overflow: auto;
  }
}
              
            
!

JS

              
                
var v = new Vue({
	el: '#main',
	data: {
/*		first_name : "V.M.",
		last_name : "Varga",
		title : "Executive Branch Manager",
		office_phone : "(555) 555-5555",
		fax : "(555) 555-5555",
		mobile_phone : "(555) 555-5555",
		email_address : "vm@narwhal.com",
		line_1 : "",
		line_2 : "111 Main Street",
		line_3 : "Minneapolis, MN 55111",
		line_4 : "www.narwhal.com",*/
		first_name : "FirstName",
		last_name : "LastName",
		title : "Title",
		office_phone : "000.000.0000",
		fax : "000.000.0000",
		mobile_phone : "000.000.0000",
		email_address : "email@email.com",
		line_1 : "AddressLine_1",
		line_2 : "AddressLine_2",
		line_3 : "AddressLine_3",
		line_4 : "AddressLine_4"
	},
  watch: {
    title : function(){
    	Vue.nextTick(function () { adjustText("title"); }.bind(this));
    },
    first_name : function(){
    	Vue.nextTick(function () { adjustText("full-name"); }.bind(this));
    },
    last_name : function(){
    	Vue.nextTick(function () { adjustText("full-name"); }.bind(this));
    },
    office_phone : function(){
    	Vue.nextTick(function () { adjustText("contact-block"); }.bind(this));
    },
    fax : function(){
    	Vue.nextTick(function () { adjustText("contact-block"); }.bind(this));
    },
    mobile_phone : function(){
    	Vue.nextTick(function () { adjustText("contact-block"); }.bind(this));
    },
    email_address : function(){
    	Vue.nextTick(function () { adjustText("contact-block"); }.bind(this));
    }
  },
  methods : {
  	adjustAllText : function(){
	  	var adjustTextIds = [
	  		"title",
	  		"full-name",
	  		"contact-block"
  		];
	  	for (var i = 0; i < adjustTextIds.length; i++) {
	  		adjustText(adjustTextIds[i]);
	  	}
  	}
  },
  mounted : function(){
  	setTimeout(function(){
  		// can it work properly without the timeout?
  		v.adjustAllText();
  	}, 10);
  },
  updated : function(){

  }
});

$("#user-submit").click(function(ev){
	ev.preventDefault();
	var svgString = $($("#original-template").find("svg")[0]).prop("outerHTML");
	var xmlnsMatches = svgString.match(/xmlns:xlink="http:\/\/www\.w3\.org\/1999\/xlink"/g);
	// for some reason this attribute gets duplicated & appears multiple times after svg.js
	// xmlns:xlink="http://www.w3.org/1999/xlink" 
	if(xmlnsMatches.length > 1){
		svgString = svgString.replace(/xmlns:xlink="http:\/\/www\.w3\.org\/1999\/xlink"/, "");
	}
	// to download to the downloads folder:
	downloadSvgFile(svgString);

	// to post back to this page where server code is set up to accept the string
	// $.post(window.location, { svgData : svgString });
});

$(".field-entry > label").css({ "cursor" : "pointer" }).click(function(){
	// the submit button event
	$(this).next().select();
});

var metaArtKeyObj = {
	// maybe other keys will be added down the road...
	text_justification : {
		"key" : "j",
		"parameters" : {
			"l" : "left-justified",
			"c" : "center-justified",
			"r" : "right-justified",
		}
	}
};

function getMetaArtInfo(artItem){
	// meta art has a syntaxed name : [text box name]--[key 1]-[value 1]--[key 2]-[value 2]
	var idString = artItem.attr("id");
	var idStringArr = idString.split(/\-\-/g);
	var referencedItemName = idStringArr[0];
	var resObj = {};
	var thisKeyPairArr, thisMetaArtProp;
	for(var all in metaArtKeyObj){
		thisMetaArtProp = metaArtKeyObj[all];
		for (var i = 0; i < idStringArr.length; i++) {
			thisKeyPairArr = idStringArr[i].split("-");
			if(thisKeyPairArr[0] == thisMetaArtProp.key){
				resObj[all] = thisMetaArtProp.parameters[thisKeyPairArr[1]];
			}
		}
	}
	return resObj;
};

function adjustBBoxDataToMatrixDeltas(bboxObj, dx, dy){
	// the guide rectangle has coordinates relative to the svg element, and so do the textboxes
	// however, the text boxes have a transformation matrix on them, so a relative bounding box is calculated
	// using parts of the matrix string (dx and dy)
	for( var all in bboxObj ){
		if(all == "h" || all == "height" || all == "w" || all == "width"){
			continue;
		}
		if(all.indexOf("x") > -1){
			bboxObj[all] += dx;
		} else if(all.indexOf("y") > -1){
			bboxObj[all] += dy;
		}
	}
	return bboxObj;
};

function applyNewMatrixDxDyValues(artItem, dx, dy){
	var transformMatrixArray = artItem.attr("transform").match(/\d+\.?\d*/g);
	transformMatrixArray[4] = (transformMatrixArray[4] * 1) + dx;
	transformMatrixArray[5] = (transformMatrixArray[5] * 1) + dy;
	// example of the transform attribute with just the matrix, which is what Illustrator outputs:
	// transform="matrix(1 0 0 1 133.9718 53.7566)"
	artItem.attr("transform", "matrix(" + transformMatrixArray.join(" ") + ")");
};

function alignTextArtViaBBox(staticArt, dynamicArt, alignmentKey){

	var allChildTSpans = SVG.select("tspan", dynamicArt.node);
	// if text blocks contain tspans, align tspans first and only then align the textbox to the guide rectangle
	// suffice it to say, it is meant to deal only with paragraph-like <text> elements which contain rows of <tspans>
	if(allChildTSpans.members.length > 0){
		// adjust tspans here
		adjustChildTSpans(dynamicArt, alignmentKey);
	}

	// adjust the text box here
	var textBounds = (dynamicArt.bbox());
	var rectBounds = (staticArt.bbox());
	var textMatrixArray = dynamicArt.attr("transform").match(/\d+\.?\d*/g);
	var dx = textMatrixArray[4] * 1;
	var dy = textMatrixArray[5] * 1;
	// console.log("dx : " + dx + ", dy : " + dy);

	var editedTextBounds = adjustBBoxDataToMatrixDeltas(textBounds, dx, dy);
	var newDx, newDy = 0; // only horizontal transform for this purpose
	if(alignmentKey == "center-justified"){
		newDx = rectBounds.cx - editedTextBounds.cx;
	} else if(alignmentKey == "left-justified"){
		newDx = rectBounds.x - editedTextBounds.x;
	} else if(alignmentKey == "right-justified"){
		newDx = rectBounds.x2 - editedTextBounds.x2;
	}

	applyNewMatrixDxDyValues(dynamicArt, newDx, newDy);
};

function adjustChildTSpans(dynamicArt, alignmentKey){
	var allChildTSpans = SVG.select("tspan", dynamicArt.node);
	if(allChildTSpans.members.length < 1){
		return;
	}
	console.log(allChildTSpans);
	var thisTSpan, thisTSpanXLocation;
	var prevTSpan = null;
	for (var i = 0; i < allChildTSpans.members.length; i++) {
		thisTSpan = allChildTSpans.get(i);
		// getComputedTextLength saves the day, as getting bbox of tspans is not working right now (2018)
		thisTSpanWidth = thisTSpan.node.getComputedTextLength();

		if(i == 0){
			prevTSpan = thisTSpan;
			continue;
		}
		var prevTSpanWidth = prevTSpan.node.getComputedTextLength();
		var widthDiff = thisTSpanWidth - prevTSpanWidth;
		thisTSpanXLocation = thisTSpan.attr("x") * 1; // first tspan is always at x=0, sets starting value for the rest to follow
		var newDx; // only horizontal transform for this purpose
		if(alignmentKey == "center-justified"){
			newDx = widthDiff / 2;
			thisTSpan.attr("x", thisTSpanXLocation + newDx);
		} else if(alignmentKey == "left-justified"){
			thisTSpan.attr("x", "0");
		} else if(alignmentKey == "right-justified"){
			newDx = -widthDiff;
			thisTSpan.attr("x", newDx);
		}
	}

};

function adjustText(elemId){
	var groupElem = SVG.adopt($("#original-template").find("svg")[0]).select("g#" + elemId).get(0);
	var textElement = groupElem.select("text").get(0);
	var rectElement = groupElem.select("rect").get(0);

	var metaArtInfo = getMetaArtInfo(rectElement);

	alignTextArtViaBBox(rectElement, textElement, metaArtInfo.text_justification);
};

downloadSvgFile = function (text) {
	var data = new Blob([text], {
	 type: 'image/svg+xml'
	});
	// use FileSaver.js to download the file
  saveAs(data, "text-output.svg");
};

              
            
!
999px

Console