SitemagicCMS icon indicating copy to clipboard operation
SitemagicCMS copied to clipboard

SMDesigner - Designer elements should have the ability to span page

Open Jemt opened this issue 6 years ago • 1 comments

Consider the following example.


image


Using pseudo elements we can make a container "stretch" across the page, just like a header image. It would be great if this was supported out of the box for a container registered as a designer element (SMDesignerElement class).

<div class="SMDesignerElement FrontPageSection1" data-id="Front page section 1" data-preserve="true">Content aligns beautifully with the ordinary content</div>
/* Generated using Designer's default controls for designer elements */
.SMDesignerElement[data-id='Front page section 1']
{
	height: 14em;
	margin-top: 2em;
	margin-bottom: 2em;
	background: #2999C2;
	color: #FCFCFC;
}

/* Applied using Advanced in Designer */
div.FrontPageSection1
{
	padding: 1.5em;
	overflow: hidden;
}
html.SMPagesFilenameIndex div.FrontPageSection1:before, html.SMPagesEditor.SMPagesFilenameIndex div.FrontPageSection1:before
{
	content: "";
	margin-top: -1.5em; /* Same value as padding above, but as a negative */
	background: inherit;
	position: absolute;
	padding: inherit;
	padding-left: 0px;
	padding-right: 0px;
	left: 0px;
	width: 100%;
	height: inherit; /* Notice: height MUST be set in designer for this to work! */
	z-index: -1;
}

Jemt avatar Jun 01 '19 19:06 Jemt

Unfortunately the approach described above scales poorly on mobile. When the width of the screen is reduced, text takes up more space vertically. Defining a height with the 'em' unit is not sufficient. So the text can either overflow, become hidden, or cause scroll.

We need to support this using JavaScript. The example below (review - quick and dirty!) calculates the height of the designer element, and adds a pseudo element behind it that spans the page, with the same height.

SMEventHandler.AddEventHandler(document, "DOMContentLoaded", function(e)
{
	// Helpers (copied from Fit.UI)

	var UpperCaseFirst = function(str)
	{
		Fit.Validation.ExpectString(str);

		if (str === "")
			return str;

		return str[0].toUpperCase() + str.slice(1);
	}

	var ForEach = SMCore.ForEach;

	var GetComputedStyle = function(elm, style)
	{
		var res = null;

		if (window.getComputedStyle) // W3C
		{
			res = window.getComputedStyle(elm)[style];
		}
		else if (elm.currentStyle)
		{
			if (style.indexOf("-") !== -1) // Turn e.g. border-bottom-style into borderBottomStyle which is required by legacy browsers
			{
				var items = style.split("-");
				style = "";

				/*Fit.Array.*/ForEach(items, function(i)
				{
					if (style === "")
						style = i;
					else
						style += /*Fit.String.*/UpperCaseFirst(i);
				});
			}

			res = elm.currentStyle[style]; // Might return strings rather than useful values - e.g. "3em" or "medium"

			// IE Computed Style fix by Dean Edwards - http://disq.us/p/myl99x
			// Transform values such as 2em or 4pt to actual pixel values.

			if (res !== undefined && res !== null && /^\d+/.test(res) === true && res.toLowerCase().indexOf("px") === -1) // Non-pixel numeric value
			{
				// Save original value
				var orgLeft = elm.style.left;

				// Calculate pixel value
				var runtimeStyle = elm.runtimeStyle.left;
				elm.runtimeStyle.left = elm.currentStyle.left;
				elm.style.left = ((style === "fontSize") ? "1em" : res || 0); // Throws error for a value such as "medium"
				res = elm.style.pixelLeft + "px";

				// Restore value
				elm.style.left = orgLeft;
				elm.runtimeStyle.left = runtimeStyle;
			}
		}

		return (res !== undefined ? res : null);
	}

	var bars = document.querySelectorAll(".page-wide-bar");

	// Configure bars

	SMCore.ForEach(bars, function(bar)
	{
		var s = document.createElement("style");
		s.type = "text/css";
		document.getElementsByTagName("head")[0].appendChild(s);

		if (!bar.id)
		{
			bar.id = "rid_" + SMRandom.CreateGuid(); // Random ID (rid)
		}
		else if (bar.className.indexOf("SMDesignerElement") > -1 && !bar.getAttribute("data-id"))
		{
			bar.setAttribute("data-id", bar.id);
		}

		bar.__pageWideBarStyle = s;

		//bar.style.boxSizing = "border-box";
	});

	// Define updator

	var designerOpen = false;

	var updateBars = function()
	{
		SMCore.ForEach(bars, function(bar)
		{
			var newHeight = bar.offsetHeight;

			if (designerOpen === false && newHeight === bar.__prevBarOffsetHeight)
			{
				//console.log("Escaping (offset height)");
				return; // Skip
			}

			bar.__prevBarOffsetHeight = newHeight;

			// TODO: Include borders etc!
			var paddingTop = /*SMDom.*/GetComputedStyle(bar, "paddingTop");
			var paddingTopFloat = parseFloat(paddingTop);
			var paddingBottomFloat = parseFloat(/*SMDom.*/GetComputedStyle(bar, "paddingBottom"));
			var checkSum = newHeight + "#" + paddingTop + "#" + paddingTopFloat + "#" + paddingBottomFloat;

			if (bar.__prevBarCheckSum === checkSum)
			{
				//console.log("Escaping (checksum)");
				return; // Skip
			}

			bar.__prevBarCheckSum = checkSum;

			bar.__prevAlternateValue = !bar.__prevAlternateValue;

			var css = "#" + bar.id + ":before";
			css += "\n{";
			css += "\n\t content: '" + (bar.__prevAlternateValue ? "" : " ") + "';"; // Value MUST change to make the element update in Legacy IE
			css += "\n\t margin-top: -" + paddingTop + ";";
			css += "\n\t background: inherit;";
			//css += "\n\t background: orange;";
			css += "\n\t position: absolute;";
			css += "\n\t padding: inherit;";
			css += "\n\t padding-left: 0px;";
			css += "\n\t padding-right: 0px;";
			css += "\n\t left: 0px;";
			css += "\n\t width: 100%;";
			css += "\n\t height: " + (bar.offsetHeight - paddingTopFloat - paddingBottomFloat) + "px;"; // Does not take borders into account!
			css += "\n\t z-index: -1;";
			css += "\n}";

			console.log("Updating CSS: ", css);

			if (bar.__pageWideBarStyle.styleSheet)
			{
				bar.__pageWideBarStyle.styleSheet.cssText = css; // Legacy IE
			}
			else
			{
				bar.__pageWideBarStyle.innerHTML = css;
			}
		});
	}

	updateBars();

	// Monitor - update when necessary

	setInterval(function() { updateBars(); }, (designerOpen === true ? 500 : 1500));
	SMEventHandler.AddEventHandler(window, "resize", function(e) { updateBars(); });
});

Jemt avatar Jun 06 '19 06:06 Jemt