Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SMDesigner - Designer elements should have the ability to span page #110

Open
Jemt opened this issue Jun 1, 2019 · 1 comment
Open

SMDesigner - Designer elements should have the ability to span page #110

Jemt opened this issue Jun 1, 2019 · 1 comment

Comments

@Jemt
Copy link
Owner

Jemt commented Jun 1, 2019

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
Copy link
Owner Author

Jemt commented Jun 6, 2019

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(); });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant