Refactor Javascript and Stylesheet loading
This commit is contained in:
parent
cc40733cff
commit
963148c639
|
@ -1,4 +1,5 @@
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Oqtane.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.UI
|
namespace Oqtane.UI
|
||||||
|
@ -56,13 +57,13 @@ namespace Oqtane.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeMeta(string id, string attribute, string name, string content)
|
public Task IncludeMeta(string id, string attribute, string name, string content, string key)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<object>(
|
_jsRuntime.InvokeAsync<object>(
|
||||||
"Oqtane.Interop.includeMeta",
|
"Oqtane.Interop.includeMeta",
|
||||||
id, attribute, name, content);
|
id, attribute, name, content, key);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -71,13 +72,13 @@ namespace Oqtane.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeLink(string id, string rel, string url, string type, string integrity, string crossorigin)
|
public Task IncludeLink(string id, string rel, string href, string type, string integrity, string crossorigin, string key)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<object>(
|
_jsRuntime.InvokeAsync<object>(
|
||||||
"Oqtane.Interop.includeLink",
|
"Oqtane.Interop.includeLink",
|
||||||
id, rel, url, type, integrity, crossorigin);
|
id, rel, href, type, integrity, crossorigin, key);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -86,13 +87,28 @@ namespace Oqtane.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeScript(string id, string src, string content, string location, string integrity, string crossorigin)
|
public Task IncludeLinks(object[] links)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeAsync<object>(
|
||||||
|
"Oqtane.Interop.includeLinks",
|
||||||
|
(object) links);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task IncludeScript(string id, string src, string integrity, string crossorigin, string content, string location, string key)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<object>(
|
_jsRuntime.InvokeAsync<object>(
|
||||||
"Oqtane.Interop.includeScript",
|
"Oqtane.Interop.includeScript",
|
||||||
id, src, content, location, integrity, crossorigin);
|
id, src, integrity, crossorigin, content, location, key);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -101,13 +117,13 @@ namespace Oqtane.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeCSS(string id, string url)
|
public Task IncludeScripts(object[] scripts)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<object>(
|
_jsRuntime.InvokeAsync<object>(
|
||||||
"Oqtane.Interop.includeLink",
|
"Oqtane.Interop.includeScripts",
|
||||||
id, "stylesheet", url, "text/css");
|
(object)scripts);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -131,7 +147,6 @@ namespace Oqtane.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ValueTask<string> GetElementByName(string name)
|
public ValueTask<string> GetElementByName(string name)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -23,31 +23,31 @@
|
||||||
await interop.UpdateTitle(PageState.Site.Name + " - " + PageState.Page.Name);
|
await interop.UpdateTitle(PageState.Site.Name + " - " + PageState.Page.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update page resources
|
// include page resources
|
||||||
int stylesheet = 0;
|
var links = new List<object>();
|
||||||
int script = 0;
|
var scripts = new List<object>();
|
||||||
foreach (Resource resource in PageState.Page.Resources)
|
foreach (Resource resource in PageState.Page.Resources)
|
||||||
{
|
{
|
||||||
switch (resource.ResourceType)
|
switch (resource.ResourceType)
|
||||||
{
|
{
|
||||||
case ResourceType.Stylesheet:
|
case ResourceType.Stylesheet:
|
||||||
stylesheet += 1;
|
links.Add(new { id = "app-stylesheet" + links.Count.ToString("00"), rel = "stylesheet", href = resource.Url, type = "text/css", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", key = "" });
|
||||||
await interop.IncludeLink("app-stylesheet" + stylesheet.ToString("00"), "stylesheet", resource.Url, "text/css", resource.Integrity ?? "", resource.CrossOrigin ?? "");
|
|
||||||
break;
|
break;
|
||||||
case ResourceType.Script:
|
case ResourceType.Script:
|
||||||
script += 1;
|
scripts.Add(new { id = "app-script" + scripts.Count.ToString("00"), src = resource.Url, integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", content = "", location = "body", key = "" });
|
||||||
await interop.IncludeScript("app-script" + script.ToString("00"), resource.Url, "", "body", resource.Integrity ?? "", resource.CrossOrigin ?? "");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// remove any page resources references which are no longer required for this page
|
await interop.IncludeLinks(links.ToArray());
|
||||||
await interop.RemoveElementsById("app-stylesheet", "app-stylesheet" + (stylesheet + 1).ToString("00"), "");
|
await interop.IncludeScripts(scripts.ToArray());
|
||||||
await interop.RemoveElementsById("app-script", "app-script" + (script + 1).ToString("00"), "");
|
// remove any page resource references which are no longer required for this page
|
||||||
|
await interop.RemoveElementsById("app-stylesheet", "app-stylesheet" + links.Count.ToString("00"), "");
|
||||||
|
await interop.RemoveElementsById("app-script", "app-script" + scripts.Count.ToString("00"), "");
|
||||||
|
|
||||||
// add favicon
|
// add favicon
|
||||||
if (PageState.Site.FaviconFileId != null)
|
if (PageState.Site.FaviconFileId != null)
|
||||||
{
|
{
|
||||||
await interop.IncludeLink("fav-icon", "shortcut icon", Utilities.ContentUrl(PageState.Alias, PageState.Site.FaviconFileId.Value), "image/x-icon", "", "");
|
await interop.IncludeLink("app-favicon", "shortcut icon", Utilities.ContentUrl(PageState.Alias, PageState.Site.FaviconFileId.Value), "image/x-icon", "", "", "id");
|
||||||
}
|
}
|
||||||
// add PWA support
|
// add PWA support
|
||||||
if (PageState.Site.PwaIsEnabled)
|
if (PageState.Site.PwaIsEnabled)
|
||||||
|
@ -97,10 +97,10 @@
|
||||||
"const serialized = JSON.stringify(manifest); " +
|
"const serialized = JSON.stringify(manifest); " +
|
||||||
"const blob = new Blob([serialized], {type: 'application/javascript'}); " +
|
"const blob = new Blob([serialized], {type: 'application/javascript'}); " +
|
||||||
"const url = URL.createObjectURL(blob); " +
|
"const url = URL.createObjectURL(blob); " +
|
||||||
"document.getElementById('pwa-manifest').setAttribute('href', url); " +
|
"document.getElementById('app-manifest').setAttribute('href', url); " +
|
||||||
"} " +
|
"} " +
|
||||||
", 1000);";
|
", 1000);";
|
||||||
await interop.IncludeScript("pwa-manifestscript", "", manifest, "body", "", "");
|
await interop.IncludeScript("app-pwa", "", "", "", manifest, "body", "id");
|
||||||
|
|
||||||
// service worker must be in root of site
|
// service worker must be in root of site
|
||||||
string serviceworker = "if ('serviceWorker' in navigator) { " +
|
string serviceworker = "if ('serviceWorker' in navigator) { " +
|
||||||
|
@ -110,6 +110,6 @@
|
||||||
"console.log('ServiceWorker Registration Failed ', err); " +
|
"console.log('ServiceWorker Registration Failed ', err); " +
|
||||||
"}); " +
|
"}); " +
|
||||||
"}";
|
"}";
|
||||||
await interop.IncludeScript("pwa-serviceworker", "", serviceworker, "body", "", "");
|
await interop.IncludeScript("app-serviceworker", "", "", "", serviceworker, "body", "id");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||||
<tags>oqtane framework</tags>
|
<tags>oqtane</tags>
|
||||||
<releaseNotes>Initial Release</releaseNotes>
|
<releaseNotes>Initial Release</releaseNotes>
|
||||||
<summary>A modular application framework for Blazor</summary>
|
<summary>A modular application framework for Blazor</summary>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||||
<tags>oqtane framework</tags>
|
<tags>oqtane</tags>
|
||||||
<releaseNotes>Initial Release</releaseNotes>
|
<releaseNotes>Initial Release</releaseNotes>
|
||||||
<summary>A modular application framework for Blazor</summary>
|
<summary>A modular application framework for Blazor</summary>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||||
<tags>oqtane framework</tags>
|
<tags>oqtane</tags>
|
||||||
<releaseNotes>Initial Release</releaseNotes>
|
<releaseNotes>Initial Release</releaseNotes>
|
||||||
<summary>A modular application framework for Blazor</summary>
|
<summary>A modular application framework for Blazor</summary>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<title>Oqtane</title>
|
<title>Oqtane</title>
|
||||||
<base href="~/" />
|
<base href="~/" />
|
||||||
<link id="fav-icon" rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link id="app-favicon" rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||||
<!-- stub the PWA manifest but defer the assignment of href -->
|
<!-- stub the PWA manifest but defer the assignment of href -->
|
||||||
<link id="pwa-manifest" rel="manifest" />
|
<link id="app-manifest" rel="manifest" />
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
<link href="css/app.css" rel="stylesheet" />
|
<link rel="stylesheet" href="css/app.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@(Html.AntiForgeryToken())
|
@(Html.AntiForgeryToken())
|
||||||
|
|
|
@ -27,9 +27,9 @@ Oqtane.Interop = {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
includeMeta: function (id, attribute, name, content) {
|
includeMeta: function (id, attribute, name, content, key) {
|
||||||
var meta;
|
var meta;
|
||||||
if (id !== "") {
|
if (id !== "" && key === "id") {
|
||||||
meta = document.getElementById(id);
|
meta = document.getElementById(id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -50,13 +50,13 @@ Oqtane.Interop = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
includeLink: function (id, rel, url, type, integrity, crossorigin) {
|
includeLink: function (id, rel, href, type, integrity, crossorigin, key) {
|
||||||
var link;
|
var link;
|
||||||
if (id !== "") {
|
if (id !== "" && key === "id") {
|
||||||
link = document.getElementById(id);
|
link = document.getElementById(id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
link = document.querySelector("link[href=\"" + CSS.escape(url) + "\"]");
|
link = document.querySelector("link[href=\"" + CSS.escape(href) + "\"]");
|
||||||
}
|
}
|
||||||
if (link === null) {
|
if (link === null) {
|
||||||
link = document.createElement("link");
|
link = document.createElement("link");
|
||||||
|
@ -67,7 +67,7 @@ Oqtane.Interop = {
|
||||||
if (type !== "") {
|
if (type !== "") {
|
||||||
link.type = type;
|
link.type = type;
|
||||||
}
|
}
|
||||||
link.href = url;
|
link.href = href;
|
||||||
if (integrity !== "") {
|
if (integrity !== "") {
|
||||||
link.integrity = integrity;
|
link.integrity = integrity;
|
||||||
}
|
}
|
||||||
|
@ -87,10 +87,10 @@ Oqtane.Interop = {
|
||||||
} else {
|
} else {
|
||||||
link.removeAttribute('type');
|
link.removeAttribute('type');
|
||||||
}
|
}
|
||||||
if (link.href !== url) {
|
if (link.href !== this.getAbsoluteUrl(href)) {
|
||||||
link.removeAttribute('integrity');
|
link.removeAttribute('integrity');
|
||||||
link.removeAttribute('crossorigin');
|
link.removeAttribute('crossorigin');
|
||||||
link.setAttribute('href', url);
|
link.setAttribute('href', href);
|
||||||
}
|
}
|
||||||
if (integrity !== "") {
|
if (integrity !== "") {
|
||||||
if (link.integrity !== integrity) {
|
if (link.integrity !== integrity) {
|
||||||
|
@ -108,11 +108,19 @@ Oqtane.Interop = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
includeScript: function (id, src, content, location, integrity, crossorigin) {
|
includeLinks: function (links) {
|
||||||
|
for (let i = 0; i < links.length; i++) {
|
||||||
|
this.includeLink(links[i].id, links[i].rel, links[i].href, links[i].type, links[i].integrity, links[i].crossorigin, links[i].key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
includeScript: function (id, src, integrity, crossorigin, content, location, key) {
|
||||||
var script;
|
var script;
|
||||||
if (id !== "") {
|
if (id !== "" && key === "id") {
|
||||||
script = document.getElementById(id);
|
script = document.getElementById(id);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
script = document.querySelector("script[src=\"" + CSS.escape(src) + "\"]");
|
||||||
|
}
|
||||||
if (script === null) {
|
if (script === null) {
|
||||||
script = document.createElement("script");
|
script = document.createElement("script");
|
||||||
if (id !== "") {
|
if (id !== "") {
|
||||||
|
@ -131,16 +139,17 @@ Oqtane.Interop = {
|
||||||
script.innerHTML = content;
|
script.innerHTML = content;
|
||||||
}
|
}
|
||||||
script.async = false;
|
script.async = false;
|
||||||
if (location === 'head') {
|
this.loadScript(script, location)
|
||||||
document.head.appendChild(script);
|
.then(() => {
|
||||||
}
|
console.log(src + ' loaded');
|
||||||
if (location === 'body') {
|
})
|
||||||
document.body.appendChild(script);
|
.catch(() => {
|
||||||
}
|
console.error(src + ' failed');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (src !== "") {
|
if (src !== "") {
|
||||||
if (script.src !== src) {
|
if (script.src !== this.getAbsoluteUrl(src)) {
|
||||||
script.removeAttribute('integrity');
|
script.removeAttribute('integrity');
|
||||||
script.removeAttribute('crossorigin');
|
script.removeAttribute('crossorigin');
|
||||||
script.src = src;
|
script.src = src;
|
||||||
|
@ -167,6 +176,32 @@ Oqtane.Interop = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
loadScript: function (script, location) {
|
||||||
|
if (location === 'head') {
|
||||||
|
document.head.appendChild(script);
|
||||||
|
}
|
||||||
|
if (location === 'body') {
|
||||||
|
document.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
script.onload = res();
|
||||||
|
script.onerror = rej();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
includeScripts: function (scripts) {
|
||||||
|
for (let i = 0; i < scripts.length; i++) {
|
||||||
|
this.includeScript(scripts[i].id, scripts[i].src, scripts[i].integrity, scripts[i].crossorigin, scripts[i].content, scripts[i].location, scripts[i].key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getAbsoluteUrl: function (url) {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
getAbsoluteUrl = function (url) {
|
||||||
|
a.href = url;
|
||||||
|
return a.href;
|
||||||
|
}
|
||||||
|
return getAbsoluteUrl(url);
|
||||||
|
},
|
||||||
removeElementsById: function (prefix, first, last) {
|
removeElementsById: function (prefix, first, last) {
|
||||||
var elements = document.querySelectorAll('[id^=' + prefix + ']');
|
var elements = document.querySelectorAll('[id^=' + prefix + ']');
|
||||||
for (var i = elements.length - 1; i >= 0; i--) {
|
for (var i = elements.length - 1; i >= 0; i--) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user