12 | */
13 | export class App {
14 | async render(solidUI,app){
15 | let appString = "";
16 | try {
17 | //let response=await panes.UI.store.fetcher.webOperation('GET',app.theme);
18 | let response = await window.fetch(app.theme);
19 | appString = solidUI.fillTemplate(await response.text(),[app]);
20 | }
21 | catch(e){console.log(e)}
22 | app = solidUI.setDefaults(app);
23 | let element = solidUI.createElement('SPAN','',appString);
24 | /*
25 | currentPodMenu
26 | userMenu
27 | initialContent
28 | podRoot : storage,
29 | podName : me.name,
30 | podNick : me.nick,
31 | podWebid : me.webId,
32 | podImage : me.image,
33 | podInbox : me.inbox,
34 | podProfile : me.webId,
35 |
36 | hard-coded
37 | solidLogo
38 | loginBox
39 | on pod-load
40 | get currentPod root,name,nick,webid,image,inbox
41 | fill
42 | on login
43 | get currentUser root,name,nick,webid,image,inbox
44 | */
45 |
46 | // solidLogo
47 | //
48 | let solidLogo = element.querySelector('#solidLogo')
49 | if(solidLogo) solidLogo.src = 'https://solidproject.org/assets/img/solid-emblem.svg';
50 |
51 | // currentPodMenu
52 | //
53 | /*
54 | let menuElement = element.querySelector("#currentPodMenu");
55 | if( app.orientation==="vertical"){
56 | menuElement = element.querySelector("NAV");
57 | }
58 | const menu = await solidUI.processComponent(menuElement,app.currentPodMenu);
59 | if(menu && menuElement) menuElement.appendChild(menu);
60 |
61 |
62 | // userMenu
63 | //
64 | if(app.userMenu) {
65 | const amenu = await solidUI.processComponent(menuElement,app.userMenu);
66 | let umenu = element.querySelector('#userMenu')
67 | if( umenu) umenu.appendChild(amenu);
68 | }
69 | */
70 | // loginBox & initialContent
71 | //
72 | if(app.loginBox) await createLoginBox(element);
73 | await applyProfile(element,'','appLoad'); // munge site menu
74 |
75 | /*
76 | if(app.initialContent) {
77 | let content = await solidUI.getComponentHash(app.initialContent);
78 | content = content.content.interpolate(solidUI.vars)
79 | let main = element.querySelector('#mainMain');
80 | if(main) main.innerHTML = content;
81 | }
82 | */
83 | //console.log(element);
84 | element = await solidUI.initInternal(element);
85 | //console.log(nel);
86 | return element;
87 | }
88 | }
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/src/view/bookmarkTree.js:
--------------------------------------------------------------------------------
1 | export class BookmarkTree {
2 |
3 | constructor(){
4 | this.store = UI.rdf.graph();
5 | this.fetcher = UI.rdf.fetcher(this.store,{fetch:UI.store.fetcher._fetch});
6 | }
7 | async init(){
8 | for(let containerElm of document.getElementsByClassName('ocb')){
9 | let subject = containerElm.dataset.component
10 | this.bookmarksDisplay = containerElm.dataset.display
11 | try {
12 | subject = await this.loadUnlessLoaded(subject)
13 | containerElm = containerElm.appendChild(document.createElement('UL') )
14 | await this.getTopic(subject,containerElm,this.bookmarksDisplay,'start')
15 | document.getElementById('ocbStart').click();
16 | }
17 | catch(e){ alert(e) }
18 | }
19 | }
20 | async getTopic(topic,containingElement,bookmarksDisplay,start){
21 | const self=this
22 | if(typeof containingElement==="string") containingElement = document.querySelector(containingElement);
23 | bookmarksDisplay ||= containingElement.dataset.display;
24 | this.bookmarksDisplay ||= bookmarksDisplay;
25 |
26 | let book = UI.rdf.Namespace("http://www.w3.org/2002/01/bookmark#")
27 | const rdf= UI.rdf.Namespace('http://www.w3.org/2000/01/rdf-schema#')
28 | const rdfs=UI.rdf.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
29 | const ui=UI.rdf.Namespace('http://www.w3.org/ns/ui#');
30 |
31 | topic = await this.loadUnlessLoaded(topic);
32 | let topicTitle = this.store.any( topic, rdf('label'),null,topic.doc() )
33 | topicTitle = (typeof topicTitle ==="undefined") ? "???" : topicTitle.value
34 | let span = document.createElement('SPAN')
35 | span.appendChild(document.createTextNode(topicTitle))
36 | span.classList.add('caret')
37 | span.addEventListener("click", function() {
38 | let elm = this.parentElement.querySelector(".nested")
39 | if(elm) elm.classList.toggle("active");
40 | this.classList.toggle("caret-down");
41 | });
42 | let li = document.createElement('LI')
43 | if(start){
44 | span.id = "ocbStart";
45 | // containingElement.appendChild(span)
46 | }
47 | // else {
48 | li.appendChild(span)
49 | containingElement.appendChild(li)
50 | // }
51 | let subTopics = this.store.each( null, book('subTopicOf'), topic )
52 | if(subTopics.length>0){
53 | let ul = document.createElement('UL')
54 | ul.classList.add('bookmarkTree')
55 | ul.classList.add('nested')
56 | li.appendChild(ul)
57 | for(let t in subTopics){
58 | this.getTopic(subTopics[t],ul)
59 | }
60 | }
61 | else {
62 | let bookmarks = this.store.each( null, book('hasTopic'), topic )
63 | let ul2 = document.createElement('UL')
64 | ul2.classList.add('nested')
65 | for(let b in bookmarks){
66 | let bookmark = bookmarks[b]
67 | let bookmarkTitle = this.store.any( bookmark, rdf('label'),null,topic.doc() )
68 | let isFeed=(this.store.match(bookmark,rdfs('type'),ui('Feed'))).length;
69 | bookmarkTitle = bookmarkTitle ? bookmarkTitle.value : "???"
70 | let bookmarkLink = this.store.any( bookmark, book('recalls'),null,topic.doc() )
71 | let bookElement = document.createElement("LI")
72 | if(isFeed) bookElement.classList.add('caret')
73 | else bookElement.classList.add('item')
74 | if(isFeed){
75 | bookElement.addEventListener("click", async function() {
76 | alert("Feed Me!");
77 | });
78 | }
79 | else {
80 | bookElement.addEventListener("click", async function() {
81 | document.querySelector(self.bookmarksDisplay).innerHTML=`
`;
82 | });
83 | }
84 | bookElement.appendChild(document.createTextNode(bookmarkTitle))
85 | let d = document.createElement('DIV')
86 | d.classList.add('closed')
87 | bookElement.appendChild(d)
88 | ul2.appendChild(bookElement)
89 | }
90 | li.appendChild(ul2)
91 | }
92 | }
93 | async loadUnlessLoaded(subject){
94 | try {
95 | const base = document.location.href.replace(/\/[^\/]*$/,'/')
96 | subject = (typeof subject==="string") ? subject : subject.uri
97 | subject = subject.match('//') ? subject : base + subject
98 | subject = UI.rdf.sym(subject)
99 | if(subject.termType==='BlankNode') return subject
100 | if(!this.store.any(null,null,null,subject.doc()))
101 | await this.fetcher.load(subject)
102 | }
103 | catch(e) { alert(e) }
104 | return subject
105 | }
106 | }
107 |
108 | /*
109 | window.addEventListener('DOMContentLoaded', async (event) => {
110 | const ocb = new BookmarkTree()
111 | ocb.init()
112 | })
113 | */
114 |
--------------------------------------------------------------------------------
/src/view/button.js:
--------------------------------------------------------------------------------
1 | export async function button(component){
2 | const targetElement = component.contentArea || document.body;
3 | let button = document.createElement('BUTTON');
4 | button.innerHTML = component.label;
5 | if(component.title) button.title = component.title;
6 | if(component.style) button.style = component.style;
7 | /*
8 | button.style = component.style;
9 | button.style.cursor ||= "pointer";
10 | button.style.color ||= solidUI.buttonColor;
11 | button.style.backgroundColor ||= solidUI.buttonBackgroundColor;
12 | */
13 | button = solidUI.styleButton(button,component);
14 |
15 | button.addEventListener('click',(e)=>{
16 | alert(component.onclick)
17 | window[component.onclick](e);
18 | });
19 | /*
20 | let script = `(()=>{${component.onclick}})()`;
21 | button.onclick = async ()=>{
22 | Function('"use strict";return ('+script+')')();
23 | };
24 | */
25 | targetElement.appendChild(button);
26 | }
27 |
--------------------------------------------------------------------------------
/src/view/buttonListMenu.js:
--------------------------------------------------------------------------------
1 | export async function buttonListMenu(options){
2 | if(options.displayArea && options.startingContent){
3 | await solidUI.util.show('',options.startingContent,'',options.displayArea);
4 | }
5 | let displayIn = options.displayArea;
6 | displayIn=typeof displayIn==="string" ?document.querySelector(displayIn) :displayIn;
7 | let div = document.createElement('DIV');
8 | // div.id = options.contentSource.replace(/.*\#/,'');
9 | let html = "";
10 | let parts = options.dataSource;
11 | if(typeof parts.length==="undefined")parts=[parts];
12 | for(let p of parts){
13 | let attrs = "";
14 | let b = document.createElement('BUTTON');
15 | b.dataset.link = p.link || p.dataSource;
16 | b.dataset.label = p.label;
17 | b.dataset.linktype = p.linktype || p.pluginType;
18 | b.innerHTML = p.label;
19 | b.value = p.dataSource;
20 | b = solidUI.styleButton(b,options);
21 | b.style['font-size'] = "100%";
22 | b.addEventListener('click',async(e)=>{
23 | return solidUI.handleLinkClick(e,options);
24 | /*
25 | e.preventDefault();
26 | let link = b.dataset.link;
27 | let linkType = b.dataset.linktype || "";
28 | if(solidUI.hideTabulator) solidUI.hideTabulator();
29 | if(linkType==='Replace'){
30 | window.location.href=link;
31 | }
32 | else if(linkType==='External'){
33 | return u.showIframeSrc(link,options.displayArea);
34 | }
35 | else if(linkType==='SolidOS'){
36 | return u.show('SolidOSLink',link,null,null,null,options)
37 | }
38 | else if(linkType==='Component') {
39 | let newDiv = document.createElement('DIV');
40 | newDiv.dataset["suic"]=link;
41 | displayIn.innerHTML = "";
42 | displayIn.appendChild(newDiv);
43 | displayIn = await solidUI.initInternal(displayIn) ;
44 | }
45 | */
46 | });
47 | div.appendChild(b)
48 | }
49 | div.style['text-align']="center";
50 | return div;
51 | }
52 |
--------------------------------------------------------------------------------
/src/view/buttonListMenu.old.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export async function buttonListMenu(json){
4 | if(json.displayArea && json.startingContent){
5 | await solidUI.util.show('',json.startingContent,'',json.displayArea);
6 | }
7 | let div = document.createElement('DIV');
8 | div.id = json.contentSource.replace(/.*\#/,'');
9 | let html = "";
10 | // if(typeof json.dataSource==="string") json.dataSource = await solidUI.processComponentSubject(json.dataSource);
11 | //console.log(33,json.dataSource)
12 | for(let ds of json.dataSource){
13 | let attrs = "";
14 | if(!ds.dataSource) {
15 | ds = await solidUI.getComponentHash(ds);
16 | }
17 | let b = document.createElement('BUTTON');
18 | for(let k of Object.keys(ds)){
19 | b.setAttribute(`data-${k}`,ds[k]);
20 | }
21 | b.innerHTML = ds.label;
22 | b = solidUI.styleButton(b,json);
23 | b.addEventListener('click',async(e)=>{
24 | e.preventDefault();
25 | let link = b.getAttribute('data-link') || b.getAttribute('data-dataSource')
26 | await solidUI.showPage(null,{link,displayArea:json.displayArea},ds);
27 | });
28 | div.appendChild(b)
29 | }
30 | let targetElement;
31 | try{ targetElement = document.querySelector(json.contentArea); }
32 | catch(e) { targetElement = document.createElement('DIV'); }
33 | targetElement.innerHTML = "";
34 | targetElement.appendChild(div)
35 | return targetElement
36 |
37 | let buttons = targetElement.querySelectorAll('BUTTON');
38 | for(let button of buttons){
39 | button = solidUI.styleButton(button,json);
40 | let tag = button.getAttribute('about');
41 | button.addEventListener('click',async(e)=>{
42 | e.preventDefault();
43 | let link = button.getAttribute('data-link') || button.getAttribute('data-dataSource')
44 | await solidUI.showPage(null,{link,displayArea:targetElement});
45 | });
46 | }
47 | return targetElement;
48 | }
49 |
--------------------------------------------------------------------------------
/src/view/componentButton.js:
--------------------------------------------------------------------------------
1 | export async function componentButton(thing){
2 |
3 | let component = thing;
4 | if(typeof thing!="object") component = await getButtonComponent(thing);
5 | let button = document.createElement('BUTTON');
6 | button.innerHTML = component.icon ?component.icon :component.label;
7 | button.addEventListener('click',async (e)=>{
8 | await solidUI.processComponent(null,component.dataSource);
9 | });
10 | button.style = component.style;
11 | button.style.cursor ||= "pointer";
12 | button.style.background ||= "#2196F3";
13 | button.style.color ||= "#ffffff";
14 | button.style.padding ||= "0.5em";
15 | button.style["border-radius"] ||= "0.2em";
16 | if(component.targetSelector) component.targetSelector.appendChild(button);
17 | return button;
18 |
19 | async function getButtonComponent(uri){
20 | let ui = UI.rdf.Namespace("http://www.w3.org/ns/ui#");
21 | let c = {};
22 | uri = UI.rdf.sym(uri);
23 | await UI.store.fetcher.load(uri);
24 | c.label = (UI.store.any(uri,ui('label'))||{}).value;
25 | c.content = (UI.store.any(uri,ui('icon'))||{}).value;
26 | c.style = (UI.store.any(uri,ui('style'))||{}).value;
27 | c.headerstyle = (UI.store.any(uri,ui('headerStyle'))||{}).value;
28 | c.dataSource = (UI.store.any(uri,ui('dataSource'))||{}).value;
29 | return c;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/view/draggable.js:
--------------------------------------------------------------------------------
1 |
2 | export async function draggable(thing){
3 | let component = thing;
4 | if(typeof thing!="object") component = await getFloatComponent(thing);
5 | let id = getDraggableId(component);
6 | let draggableDomElement = document.getElementById(id);
7 |
8 | /* If it already exists, show it and return
9 | */
10 | if(draggableDomElement){
11 | draggableDomElement.style.display = "block";
12 | return;
13 | }
14 |
15 | let div = document.createElement('DIV');
16 | let header = document.createElement('DIV');
17 | let close = document.createElement('SPAN');
18 | let content = document.createElement('DIV');
19 | let pageEl = document.getElementById('right-column-tabulator');
20 | content.innerHTML = pageEl.innerHTML;
21 | pageEl.innerHTML = "";
22 | // pageEl.style.display="none";
23 | // content = await getDraggableContent(component,content);
24 | div.id = id;
25 |
26 | close.innerHTML=" X ";
27 | close.style.color = "#ffeeee";
28 | close.style["font-weight"] = "bold";
29 | close.style["margin-left"] = "2em";
30 | close.style.background = "#000000";
31 | close.style.padding = "0.2em;"
32 | close.style["border-radius"] ||= "0.2em";
33 | close.addEventListener('click',(e)=>{
34 | e.target.parentNode.parentNode.style.display = "none";
35 | });
36 |
37 |
38 | /* STYLE OF THE DRAGGABLE DIV */
39 | div.style = component.style || {};
40 | div.style.position ||= "absolute";
41 | div.style["z-index"] ||= 3;
42 | div.style.background ||= "#f1f1f1";
43 | div.style.border ||= "1px solid #d3d3d3";
44 | div.style["text-align"] ||= ":center";
45 | // div.style.height="80%";
46 | // div.style.width="80%";
47 |
48 | /* STYLE OF DRAGGABLE DIV'S HEADER */
49 | header.style = component.headerStyle || {};
50 | header.style.padding ||= "10px";
51 | header.style.cursor ||= "move";
52 | header.style["z-index"] ||= 4;
53 | header.style["text-align"] ||= "center";
54 | header.style.background ||= "#2196F3";
55 | header.style.color ||= "#ffffff";
56 |
57 | /* STYLE OF DRAGGABLE DIV'S CONTENT */
58 | content.style = component.style || {};
59 | content.style.padding ||= "1em";
60 |
61 | /* MOUSE ACTIONS */
62 | let pos1,pos2,pos3,pos4;
63 | div.onmousedown = (e)=>{ /* DRAG ELEMENT CLICK */
64 | e = e || window.event;
65 | e.preventDefault();
66 | pos3 = e.clientX;
67 | pos4 = e.clientY;
68 | document.onmouseup = (e)=>{ /* DRAG ELEMNT DROP */
69 | document.onmouseup = null;
70 | document.onmousemove = null;
71 | }
72 | document.onmousemove = (e)=>{ /* DRAG ELEMENT DRAG */
73 | e = e || window.event;
74 | e.preventDefault();
75 | pos1 = pos3 - e.clientX;
76 | pos2 = pos4 - e.clientY;
77 | pos3 = e.clientX;
78 | pos4 = e.clientY;
79 | div.style.top = (div.offsetTop - pos2) + "px";
80 | div.style.left = (div.offsetLeft - pos1) + "px";
81 | }
82 | };
83 |
84 | header.appendChild(close);
85 | div.appendChild(header);
86 | div.appendChild(content);
87 | document.body.appendChild(div);
88 | return div;
89 |
90 | /* UTILITY FUNCTIONS */
91 | function getDraggableId(component){
92 | return component.label.replace(/\s+/g,"_");
93 | }
94 | async function getDraggableContent(component,content){
95 | let ds;
96 | header.innerHTML = `
${component.label} `;
97 | if(component.content) {
98 | content.innerHTML = component.content;
99 | }
100 | else if(component.dataSource) {
101 | ds = await solidUI.processComponent(null,component.dataSource);
102 | content.appendChild( ds );
103 | }
104 | else if(component.dataSourceType) {
105 | ds=await solidUI.util.show(component.dataSourceType,null,null,null,null,component);
106 | content.appendChild( ds );
107 | }
108 | return content;
109 | }
110 | async function getDraggableComponent(uri){
111 | let ui = UI.rdf.Namespace("http://www.w3.org/ns/ui#");
112 | let c = {};
113 | uri = UI.rdf.sym(uri);
114 | await UI.store.fetcher.load(uri);
115 | c.label = (UI.store.any(uri,ui('label'))||{}).value;
116 | c.content = (UI.store.any(uri,ui('content'))||{}).value;
117 | c.style = (UI.store.any(uri,ui('style'))||{}).value;
118 | c.headerstyle = (UI.store.any(uri,ui('headerStyle'))||{}).value;
119 | c.dataSource = (UI.store.any(uri,ui('dataSource'))||{}).value;
120 | return c;
121 | }
122 |
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/src/view/extras:
--------------------------------------------------------------------------------
1 |
10 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/view/form.js:
--------------------------------------------------------------------------------
1 | import * as u from '../utils.js';
2 | /*
3 | form.render() // define options via Javascript parameters
4 | form.fromUrl() // define options via ui:Component file
5 | form.fromMem() // define options via a ui:Component string
6 |
7 | */
8 | export class Form {
9 |
10 | /**
11 | * @param {String} form - the URL of the form definition document
12 | * @param {String} formSubject - the data for the form
13 | * @param {String} [formString] - a string form definition
14 | * @param {HTMLElement} [dom=document] - DOM container to hold form
15 | * @param {Boolean} [forceReload] - empty store before loading
16 | * @param {String} [formResultDocument] - place to store form results
17 | * @param {Function} [script] - Javascript to execute on form change
18 | * @returns an HTML DIV element containing the form
19 | */
20 | async fromURL(url){
21 | let node = UI.rdf.sym(url);
22 | await UI.fetcher.load(node);
23 | return await this.render({
24 | form : url,
25 | formSubject : u.getProperty(node,'ui:formSubject'),
26 | script : u.getProperty(node,'ui:script'),
27 | resultDocument : u.getProperty(node,'ui:formResultDocument'),
28 | });
29 | }
30 | async render(o){
31 | o.form ||= o.contentSource;
32 | const dom = o.dom || document;
33 | const container = document.createElement("DIV");
34 | container.classList.add('uic-form');
35 | let form = UI.rdf.sym(o.form);
36 | let subject;
37 | if(o.formSubject) subject = UI.rdf.sym(o.formSubject) ;
38 | if(o.formString){
39 | UI.rdf.parse(string,UI.store,o.form,'text/turtle');
40 | }
41 | else await UI.store.fetcher.load(o.form);
42 | if(!subject){
43 | let fSubj = UI.rdf.sym('http://www.w3.org/ns/ui#formSubject');
44 | subject = UI.store.any(form,fSubj)
45 | }
46 | if(o.forceReload){
47 | if(subject && subject.doc) UI.store.removeDocument(subject.doc());
48 | }
49 | if(subject) await UI.store.fetcher.load(subject.doc());
50 | else {
51 | container.innerHTML="ERROR : Could not load form subject "
52 | return container;
53 | }
54 | const title = document.createElement("H2");
55 | let doc = o.formResultDocument;
56 | if(subject && !doc && subject.doc) doc = subject.doc();
57 | const script = o.script || function (){
58 | UI.store.fetcher.putBack(subject) // tempory work-around ui:ordered bug
59 | };
60 | try {
61 | UI.widgets.appendForm(dom, container, {}, subject, form, doc, script);
62 | }
63 | catch(e){
64 | // console.log(dom,container,subject,form,doc)
65 | container.innerHTML = "FORM ERROR:"+e;
66 | }
67 | return container;
68 | }
69 |
70 | }
71 |
72 | /* OLD
73 | async render(solidUI,options){
74 | const container = document.createElement("DIV",'uic-form');
75 | const dom = window.document;
76 | const form = await solidUI.loadUnlessLoaded(options.form);
77 | await solidUI.loadUnlessLoaded(options.formSubject);
78 | const subject = await solidUI.loadUnlessLoaded(options.formSubject);
79 | if(!subject) return console.log("ERROR : Couldn not load form subject ",options.formSubject)
80 | let doc = options.formResultDocument;
81 | if(!doc && subject.doc) doc = subject.doc();
82 | const script = options.script || function(){};
83 | try {
84 | UI.widgets.appendForm(dom, container, {}, subject, form, doc, script);
85 | }
86 | catch(e){return console.log(e)}
87 | if(options.onchange) {
88 | const vals = container.querySelectorAll('.formFieldValue button');
89 | for(let v of vals){
90 | v.onclick = "alert(3)";
91 | }
92 | }
93 | return container;
94 | }
95 |
96 | */
97 |
--------------------------------------------------------------------------------
/src/view/linked-bookmarks.js:
--------------------------------------------------------------------------------
1 | export class OpenCultureBrowser {
2 |
3 | constructor(){
4 | this.store = UI.rdf.graph();
5 | this.fetcher = UI.rdf.fetcher(this.store);
6 | }
7 | async init(){
8 | for(let containerElm of document.getElementsByClassName('ocb')){
9 | let subject = containerElm.dataset.component
10 | this.bookmarksDisplay = containerElm.dataset.display
11 | try {
12 | subject = await this.loadUnlessLoaded(subject)
13 | containerElm = containerElm.appendChild(document.createElement('UL') )
14 | await this.getTopic(subject,containerElm,'start')
15 | document.getElementById('ocbStart').click();
16 | }
17 | catch(e){ alert(e) }
18 | }
19 | }
20 | async getTopic(topic,containingElement,start){
21 | const self=this
22 |
23 | let book = UI.rdf.Namespace("http://www.w3.org/2002/01/bookmark#")
24 | const rdf= UI.rdf.Namespace('http://www.w3.org/2000/01/rdf-schema#')
25 | const rdfs=UI.rdf.Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#')
26 | const ui=UI.rdf.Namespace('http://www.w3.org/ns/ui#');
27 |
28 | topic = await this.loadUnlessLoaded(topic);
29 | let topicTitle = this.store.any( topic, rdf('label'),null,topic.doc() )
30 | topicTitle = (typeof topicTitle ==="undefined") ? "???" : topicTitle.value
31 | let span = document.createElement('SPAN')
32 | span.appendChild(document.createTextNode(topicTitle))
33 | span.classList.add('caret')
34 | span.addEventListener("click", function() {
35 | this.parentElement.querySelector(".nested").classList.toggle("active");
36 | this.classList.toggle("caret-down");
37 | });
38 | let li = document.createElement('LI')
39 | li.appendChild(span)
40 | containingElement.appendChild(li)
41 | if(start){
42 | span.id = "ocbStart";
43 | }
44 | let subTopics = this.store.each( null, book('subTopicOf'), topic )
45 | if(subTopics.length>0){
46 | let ul = document.createElement('UL')
47 | ul.classList.add('nested')
48 | li.appendChild(ul)
49 | for(let t in subTopics){
50 | this.getTopic(subTopics[t],ul)
51 | }
52 | }
53 | else {
54 | let bookmarks = this.store.each( null, book('hasTopic'), topic )
55 | let ul2 = document.createElement('UL')
56 | ul2.classList.add('nested')
57 | for(let b in bookmarks){
58 | let bookmark = bookmarks[b]
59 | let bookmarkTitle = this.store.any( bookmark, rdf('label'),null,topic.doc() )
60 | let isFeed=(this.store.match(bookmark,rdfs('type'),ui('Feed'))).length;
61 | bookmarkTitle = bookmarkTitle ? bookmarkTitle.value : "???"
62 | let bookmarkLink = this.store.any( bookmark, book('recalls'),null,topic.doc() )
63 | let bookElement = document.createElement("LI")
64 | if(isFeed) bookElement.classList.add('caret')
65 | else bookElement.classList.add('item')
66 | if(isFeed){
67 | bookElement.addEventListener("click", async function() {
68 | alert("Feed Me!");
69 | });
70 | }
71 | else {
72 | bookElement.addEventListener("click", async function() {
73 | // document.getElementById(self.bookmarksDisplay).src=bookmarkLink.uri
74 | document.getElementById(self.bookmarksDisplay).innerHTML=`
`;
75 | });
76 | }
77 | bookElement.appendChild(document.createTextNode(bookmarkTitle))
78 | let d = document.createElement('DIV')
79 | d.classList.add('closed')
80 | bookElement.appendChild(d)
81 | ul2.appendChild(bookElement)
82 | }
83 | li.appendChild(ul2)
84 | }
85 | }
86 | async loadUnlessLoaded(subject){
87 | try {
88 | const base = document.location.href.replace(/\/[^\/]*$/,'/')
89 | subject = (typeof subject==="string") ? subject : subject.uri
90 | subject = subject.match('//') ? subject : base + subject
91 | subject = UI.rdf.sym(subject)
92 | if(subject.termType==='BlankNode') return subject
93 | if(!this.store.any(null,null,null,subject.doc()))
94 | await this.fetcher.load(subject)
95 | }
96 | catch(e) { alert(e) }
97 | return subject
98 | }
99 | }
100 |
101 | window.addEventListener('DOMContentLoaded', async (event) => {
102 | const ocb = new OpenCultureBrowser()
103 | ocb.init()
104 | })
105 |
106 |
--------------------------------------------------------------------------------
/src/view/mediaList.js:
--------------------------------------------------------------------------------
1 | /*
2 | mediaList()
3 | mediaItem()
4 | _fillMediaTemplate()
5 | */
6 |
7 | export async function mediaList(options){
8 | const elm = document.createElement('SPAN');
9 | for(let track of options.parts){
10 | options.id = track.id;
11 | elm.appendChild( await mediaItem(options) );
12 | }
13 | return elm;
14 | }
15 |
16 | export async function mediaItem(options){
17 | options.orientation ||= options.contentArea.dataset.orientation;
18 | options.compact ||= 1;
19 | if(options.includeMetadata || options.contentArea.dataset.includemetadata){options.compact=0};
20 | options.allowDownload ||= options.contentArea.dataset.allowdownload;
21 | let subject = UI.rdf.sym(options.id);
22 | await UI.store.fetcher.load(subject);
23 | let item = _getItemFromStore(subject);
24 | item. vertical = document.body.offsetWidth<750 || options.orientation==1;
25 | item.isVideo = false;
26 | let types = UI.store.match(subject,UI.ns.rdf('type'));
27 | for(let t of types){
28 | if(t.object.value.match(/video/i)) item.isVideo =true;
29 | }
30 | return(_fillMediaTemplate(item,options) );
31 | }
32 |
33 | function _getItemFromStore(subject){
34 | return({
35 | byArtist : (UI.store.any(subject,UI.ns.schema('byArtist'))||{}).value,
36 | encoding : (UI.store.any(subject,UI.ns.schema('encoding'))||{}).value,
37 | image : (UI.store.any(subject,UI.ns.schema('image'))||{}).value,
38 | description : (UI.store.any(subject,UI.ns.schema('description'))||{}).value,
39 | country : (UI.store.any(subject,UI.ns.schema('countryOfOrigin'))||{}).value,
40 | });
41 | }
42 |
43 | function _fillMediaTemplate(i,options){
44 | let table = document.createElement('DIV');
45 | i.download = options.allowDownload ?"" :`controlslist="nodownload"`;
46 | if(i.vertical){
47 | i.align ="center";
48 | i.width="310px";
49 | i.audioWidth="272px !important";
50 | i.imageStyle = "width:272px;margin-top:0.5rem;margin-bottom:0.4rem;";
51 | }
52 | else {
53 | i.audioWidth="272px !important";
54 | i.imageStyle = "height:180px;float:left;margin-right:1rem;margin-top:0.5rem;";
55 | i.width = "590px";
56 | i.align ="left";
57 | }
58 | if(i.isVideo){
59 | i.audio = "";
60 | i.visual = `
`;
61 | }
62 | else {
63 | i.visual = `
`;
64 | i.audio = `
`
65 | }
66 | if(options.compact) {
67 | let wrapper = document.createElement('SPAN');
68 | wrapper.innerHTML = i.isVideo ?i.visual :i.audio;
69 | return wrapper;
70 | }
71 | table.style = `min-height:212px; margin:0.8rem;text-align:${i.align}; padding:0.5rem; border-radius:0.5rem; background:#bb99ff; color:black; width:${i.width}`;
72 | table.innerHTML = `
73 |
74 | ${i.byArtist} - ${i.country}
75 |
76 | ${i.visual}
77 |
${i.description}
78 | ${i.audio}
79 | `;
80 | return table;
81 | // else {
82 | table.innerHTML = `
83 |
84 |
85 | ${i.byArtist} - ${i.country}
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | ${i.description}
94 |
95 |
96 |
97 |
98 |
99 | `;
100 | // }
101 | return table;
102 | }
103 |
--------------------------------------------------------------------------------
/src/view/menu.js:
--------------------------------------------------------------------------------
1 | export class Menu {
2 |
3 | async render( solidUI, json,element ){
4 | if(typeof json==='string'){
5 | json = await solidUI.processComponent(element,json);
6 | }
7 | if(json.displayArea && json.landingPage){
8 | await solidUI.processComponentSubject(json.landingPage);
9 | }
10 | let nav = solidUI.createElement('NAV','solid-uic-dropdown-menu')
11 | let topUL = document.createElement('UL')
12 | let mainDisplay = document.createElement('DIV')
13 | this.pluginMenuArea = document.createElement('DIV');
14 | this.pluginMenuArea.id = "pluginMenuArea";
15 | this.pluginMenuArea.style.paddingTop = "3rem";
16 | const wrapper = solidUI.createElement('DIV');
17 | wrapper.style.width="100%";
18 | wrapper.style["overflow-x"]="hidden";
19 | topUL = _styleUL(topUL,json);
20 | wrapper.appendChild(nav);
21 | wrapper.appendChild(mainDisplay);
22 | wrapper.appendChild(this.pluginMenuArea);
23 | nav = _styleNav(nav,json);
24 | mainDisplay = _styleMain(mainDisplay,json);
25 | mainDisplay.innerHTML="";
26 | mainDisplay.classList.add('main');
27 | nav.appendChild(topUL)
28 | for(var i of json.parts){
29 | topUL.appendChild( await this.renderMenuItem(i,json,mainDisplay) )
30 | }
31 | return(wrapper);
32 | }
33 |
34 | async renderMenuItem(i,json,mainDisplay){
35 | if(i.menu && i.menu.type && i.menu.type === "SparqlQuery"){
36 | let menu = await solidUI.processComponent(null,null,i.menu);
37 | if(typeof menu==="object") i.parts = menu
38 | }
39 | if(!i.parts && i.dataSource ){
40 | if(!i.pluginType || i.pluginType!="resourceSelector"){
41 | let x = await solidUI.getComponentHash(i.dataSource);
42 | i.parts = x && x.parts ?x.parts :null;
43 | }
44 | }
45 | let li = document.createElement('LI')
46 | const sp = document.createElement('SPAN')
47 | sp.innerHTML = i.label;
48 | li.appendChild(sp)
49 | li.onmouseover = ()=>{
50 | li.style.color = solidUI.menuColor;
51 | li.style.background = solidUI.menuHighlight;
52 | }
53 | li.onmouseout = ()=>{
54 | li.style.color = solidUI.menuColor;
55 | li.style.background = solidUI.menuBackground;
56 | }
57 | if(i.popout || !i.parts){
58 | /*
59 | *
${i.label}
60 | */
61 | li.classList.add('item')
62 | //
63 | li.name = i.href || i.dataSource && i.dataSource.dataSource ?i.dataSource.dataSource :i.dataSource;
64 | li.pluginType = i.pluginType;
65 |
66 | li.dataset.link = li.name;
67 | li.dataset.linktype = i.pluginType;
68 | li.dataset.label = i.label;
69 |
70 | const self = this
71 | li.onclick = async (e)=>{
72 | let pluginURI = li.dataset.link;
73 | let pluginType = li.dataset.linktype || li.dataset.link || "";
74 | let pluginLabel = li.dataset.label;
75 | let pArea = this.pluginMenuArea;
76 | if(pluginType==="SolidOS"){
77 | pArea = document.getElementById('outline')
78 | }
79 | let newId = pluginLabel.replace(/\s/g,"_");
80 | let newArea = pArea.querySelector('#'+newId);
81 | let processedPlugin = await solidUI.processComponentSubject(pluginURI);
82 | // = Plugin JSON
83 | processedPlugin ||= i;
84 | if(processedPlugin.landingPage){
85 | await solidUI.processComponentSubject(processedPlugin.landingPage);
86 | }
87 | processedPlugin.contentArea = '#' + newId;
88 | for(let plugin of pArea.childNodes){
89 | plugin.style.display="none";
90 | }
91 | if(!newArea && pluginType != "SolidOS"){
92 | newArea = document.createElement('DIV');
93 | newArea.id = newId;
94 | pArea.appendChild(newArea);
95 | newArea.innerHTML=`
${e.target.innerHTML} `;
96 | if(processedPlugin.type){
97 | processedPlugin = await solidUI.processComponentJson(processedPlugin);
98 | newArea.appendChild(processedPlugin);
99 | }
100 | else if(!processedPlugin.dataSource || !pluginType==="SolidOS") {
101 | newArea.appendChild(processedPlugin)
102 | }
103 | if(pluginType==="resourceSelector"){
104 | newArea.appendChild(processedPlugin)
105 | }
106 | }
107 | if(newArea) {
108 | newArea.style.display="block";
109 | newArea.focus();
110 | }
111 | }
112 | li = _styleLI(li,json);
113 | }
114 | else {
115 | /*
116 |
117 | ${i.title}
118 |
120 |
121 | */
122 | li.classList.add('caret')
123 | let ul2 = document.createElement('UL')
124 | ul2.style.background="white";
125 | ul2.style.width="100%";
126 | li.appendChild(ul2)
127 | ul2.classList.add('nested')
128 | if(typeof i.parts.length==="undefined") i.parts = [i.parts];
129 | for(var m in i.parts){
130 | let newItem = i.parts[m]
131 | if(typeof newItem==='object') newItem.target=json.target;
132 | ul2.appendChild( await this.renderMenuItem(newItem,json,mainDisplay) )
133 | }
134 | }
135 | return li
136 | }
137 | }
138 |
139 | // MENU CONTAINER
140 | function _styleNav(nav,json){
141 | // nav.style.width="100%";
142 | nav.style.padding="0 !impotant";
143 | nav.style.background=json.color || solidUI.menuBackground;
144 | nav.style.color=json.background || solidUI.menuColor;
145 | nav.style.display="inline-block";
146 | nav.style.textAlign=json.position;
147 | return nav;
148 | }
149 |
150 | // INITIAL STATE OF MENU
151 | //
152 | function _styleUL(ul,json){
153 | // ul.style.width="100%";
154 | ul.style.color = solidUI.menuColor;
155 | ul.style.background = solidUI.menuBackground;
156 |
157 | ul.style.padding="0 !impotant";
158 | ul.style.margin="0 !impotant";
159 | ul.style.textAlign=json.position;
160 | ul.style['padding-inline-start']="0 !important";
161 | return ul;
162 | }
163 | // TOP MENU ITEM DISPLAY
164 | function _styleLI(li,json){
165 | li.style.cursor="pointer"
166 | li.style.display="inline-block";
167 | li.style.padding="0.5rem";
168 | li.style.margin="0.25rem";
169 | li.style.color = json.color || solidUI.menuColor;
170 | li.style.background = json.background || solidUI.menuBackground;
171 | return li;
172 | }
173 | // MENU DISPLAY
174 | function _styleMain(mainDisplay,json){
175 | mainDisplay.style.width="100%";
176 | /*
177 | mainDisplay.style.backgroundColor = 'red' || json.background || solidUI.menuBackground;
178 | mainDisplay.style.color = 'blue' || json.color || solidUI.menuColor;
179 | */
180 | return mainDisplay;
181 | }
182 |
183 |
--------------------------------------------------------------------------------
/src/view/menu.new.js:
--------------------------------------------------------------------------------
1 | export class Menu {
2 |
3 | async render( solidUI, json,element ){
4 | if(typeof json==='string'){
5 | json = await solidUI.processComponent(element,json);
6 | }
7 | let nav = solidUI.createElement('NAV')
8 | if(json.orientation==="horizontal") nav.classList.add('solid-uic-dropdown-menu');
9 | let topUL = document.createElement('UL')
10 | let mainDisplay = document.createElement('DIV')
11 | nav.style.background=json.unselBackground;
12 | nav.style.color=json.unselColor;
13 | mainDisplay.style.width="100%";
14 | mainDisplay.style.backgroundColor = json.background;
15 | mainDisplay.style.color = json.color;
16 | mainDisplay.innerHTML="";
17 | mainDisplay.classList.add('main');
18 | nav.appendChild(topUL)
19 | for(var i of json.parts){
20 | topUL.appendChild( await this.renderMenuItem(i,json,mainDisplay) )
21 | }
22 | const wrapper = solidUI.createElement('SPAN');
23 | nav.style.display="inline-block";
24 | nav.style.textAlign=json.position;
25 | topUL.style.textAlign=json.position;
26 | topUL.style.padding="0";
27 | wrapper.appendChild(nav);
28 | wrapper.appendChild(mainDisplay);
29 | return(wrapper);
30 | }
31 |
32 | async renderMenuItem(i,json,mainDisplay){
33 | if(i.menu && i.menu.type && i.menu.type === "SparqlQuery"){
34 | let menu = await solidUI.processComponent(null,null,i.menu);
35 | if(typeof menu==="object") i.parts = menu
36 | }
37 | const li = document.createElement('LI')
38 | const sp = document.createElement('SPAN')
39 | sp.innerHTML = i.label
40 | li.appendChild(sp)
41 | li.style.cursor="pointer"
42 | li.style.display = "inline-block";
43 | li.style.padding = "0.5em";
44 | li.style.backgroundColor = json.unselBackground;
45 | li.style.color = json.unselColor;
46 | li.onmouseover = ()=>{
47 | li.style.backgroundColor = json.selBackground;
48 | li.style.color = json.selColor;
49 | }
50 | li.onmouseout = ()=>{
51 | li.style.backgroundColor = json.unselBackground;
52 | li.style.color = json.unselColor;
53 | }
54 | if(i.popout || !i.parts){
55 | // i.target=json.target;
56 | /*
57 | *
${i.label}
58 | */
59 | li.classList.add('item')
60 | li.name = i.href
61 | const self = this
62 | /*
63 | li.addEventListener('click',(e)=>{
64 | window.displayLink(e,i,mainDisplay)
65 | })
66 | We can't easily override the eventListener later so use onclick instead.
67 | */
68 | li.onclick = (e)=>{
69 | i.href = e.target.parentElement.name;
70 | window.displayLink(e,i,mainDisplay)
71 | }
72 | }
73 | else {
74 | /*
75 |
76 | ${i.title}
77 |
79 |
80 | */
81 | li.classList.add('caret')
82 | let ul2 = document.createElement('UL')
83 | li.appendChild(ul2)
84 | ul2.classList.add('nested')
85 | for(var m in i.parts){
86 | let newItem = i.parts[m]
87 | if(typeof newItem==='object') newItem.target=json.target;
88 | ul2.appendChild( await this.renderMenuItem(newItem,json,mainDisplay) )
89 | }
90 | }
91 | return li
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/view/menuMenu.js:
--------------------------------------------------------------------------------
1 | export async function menuOfMenus(json){
2 | let target = document.querySelector(json.displayArea);
3 | if(target && json.startingContent){
4 | let content = await solidUI.processComponentSubject(json.startingContent)
5 | if(content) target.appendChild(content)
6 | // await solidUI.util.show('',content,'',json.displayArea);
7 | }
8 | let div = document.createElement('DIV');
9 | div.id = json.contentSource.replace(/.*\#/,'');
10 | let html = "";
11 | // if(!json.dataSource.dataSource) json.dataSource.dataSource = json.dataSource;
12 | for(let ds of json.dataSource){
13 | let component = ds.directDisplay ?ds.dataSource :ds.id
14 | ds.directDisplay ||= "";
15 | if(ds.plugin && ds.plugin.match(/External/)) ds.external = "true";
16 | html += `
${ds.label} `;
17 | }
18 | div.innerHTML = html;
19 | let targetElement = typeof json.contentArea==="string" ?document.querySelector(json.contentArea) :solidUI.currentElement;
20 | targetElement.innerHTML = "";
21 | targetElement.appendChild(div)
22 | let moreHtml = ""
23 | for(let ds2 of json.dataSource){
24 | let div2 = document.createElement('DIV');
25 | div2.id=ds2.label.replace(/\s*/g,'_');
26 | div2.setAttribute('data-suic',ds2.id);
27 | div2.style="display:none";
28 | targetElement.appendChild(div2);
29 | }
30 | let buttons = targetElement.querySelectorAll('BUTTON');
31 | for(let button of buttons){
32 | button = solidUI.styleButton(button,json);
33 | let tag = button.getAttribute('about');
34 | button.addEventListener('click',async(e)=>{
35 | e.preventDefault();
36 | let external = button.getAttribute('data-external');
37 | external = external==="undefined" ?null :external;
38 | let direct = button.getAttribute('data-directDisplay');
39 | direct = direct==="undefined" ?null :direct;
40 | let href = button.getAttribute('about');
41 | if(direct){
42 | await solidUI.showPage(null,{link:href,displayArea:targetElement});
43 | return;
44 | }
45 | if(external) {
46 | return solidUI.processComponentSubject(href)
47 | }
48 | let divs = targetElement.querySelectorAll(json.contentArea + ' > DIV');
49 | for(let d of divs){
50 | let target = d.getAttribute('data-suic');
51 | if(target===tag){
52 | d.style.display="block";
53 | await solidUI.activateComponent(d,targetElement);
54 | }
55 | else d.style.display="none";
56 | }
57 | });
58 | }
59 | return targetElement;
60 | }
61 |
--------------------------------------------------------------------------------
/src/view/modal.js:
--------------------------------------------------------------------------------
1 | export class Modal {
2 | /*
3 | <#MyModal>
4 | a ui:Modal ;
5 | ui:label "BUTTON_LABEL" ;
6 | ui:unselColor "BUTTON_COLOR" ;
7 | ui:unselBackground "BUTTON_BACKGROUND_COLOR" ;
8 | ui:width "POPUP-BOX_WIDTH" .
9 |
10 | Modal.render({
11 | label // button label
12 | unselColor // button color
13 | unselBackground // button background color
14 | width // popup-box width
15 | height // popup-box height
16 | content // popup-box content string
17 | iframe // popup-box url for iframe
18 | });
19 | */
20 |
21 | async render (o,solidUI) {
22 | let dom = o.dom || document;
23 | let modal = document.createElement('SPAN');
24 | if(o.targetSelector){
25 | modal = dom.querySelector(o.targetSelector);
26 | }
27 | const s = _getCSS(o);
28 | if(o.iframe){
29 | let iframe = document.createElement("IFRAME");
30 | o.content = `
`;
31 | }
32 | if(!o.content && o.dataSource){
33 | o.content = (await solidUI.processComponentSubject(o.dataSource)).outerHTML;
34 | }
35 | modal.innerHTML = `
36 |
37 | ${o.label}
38 |
39 |
40 |
41 |
42 | ×
43 |
44 | ${o.content}
45 |
46 |
47 | `;
48 | let button = modal.querySelector('button')
49 | button = solidUI.styleButton(button,o);
50 | if(solidUI) modal = await solidUI.initInternal(modal);
51 | if(o.contentArea) o.contentArea.appendChild(modal)
52 | return modal;
53 | }
54 | }
55 | window.openModal = function (element,action){
56 | element.parentElement.children[1].style.display = "block" ;
57 | }
58 | window.closeModal = function (element,action){
59 | element.parentElement.parentElement.style.display = "none" ;
60 | }
61 |
62 | function _getCSS(current){
63 | return {
64 | "button": `
65 | background-color:${current.darkBackground};
66 | color:${current.unselColor};
67 | cursor:pointer;
68 | `,
69 | ".modal": `
70 | display: none; /* Hidden by default */
71 | position: fixed; /* Stay in place */
72 | left: 0;
73 | top: 0;
74 | overflow: auto; /* Enable scroll if needed */
75 | background-color: rgb(0,0,0); /* Fallback color */
76 | background-color: rgba(0,0,0,0.8); /* Black w/ opacity */
77 | width: 100%; /* Full width */
78 | height: 100%; /* Full height */
79 | z-index:20000;
80 | text-align:center;
81 | `,
82 | ".modal-content": `
83 | // background-color: #fefefe;
84 | background-color: ${current.lightBackground};
85 | margin: 5% auto; /* 15% from the top and centered */
86 | width:80vw;
87 | height:85vh;
88 | padding: 1rem;
89 | border: 1px solid #888;
90 | border-radius:0.5rem;
91 | `,
92 | ".close": `
93 | color:red;
94 | text-align:right;
95 | margin-bottom: 0.25rem;
96 | font-size: 2rem;
97 | font-weight: bold;
98 | cursor:pointer;
99 | `
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/view/optionSelector.js:
--------------------------------------------------------------------------------
1 | /*
2 | color // a ui:Color for text of the selector
3 | background // a ui:Color for the background of the selector
4 | highlight // a ui:Color for the selector options background
5 | size // the number of options to show
6 | parts // an array of options
7 | dataSource // a component address that yields an array of options
8 | onchange // action to take on selection
9 | */
10 | export function optionSelector(j) {
11 | const hasSuic = typeof solidUI !="undefined";
12 | j.color ||= hasSuic ?solidUI.menuColor :"#000000";
13 | j.background ||= hasSuic ?solidUI.menuBackground : "#c0c0c0";
14 | j.highlight ||= hasSuic ?solidUI.menuHighlight : "#909090";
15 | j.size ||= hasSuic ?solidUI.selectorSize :0;
16 | const borderColor = j.color;
17 | const wrapper = document.createElement('DIV');
18 | let collectionSelector = document.createElement('DIV');
19 | collectionSelector.style = `border:1px solid ${borderColor};border-bottom:none`;
20 | collectionSelector.style.background=j.background;
21 | collectionSelector.style.color= j.color;
22 | j.parts ||= j.dataSource.parts;
23 | const firstOption = j.label || j.parts[0] ?(j.parts[0]).label || j.parts[0]:"";
24 | collectionSelector.innerHTML = `
${firstOption} ⌄
`;
25 | let collectionsList = document.createElement('DIV');
26 | collectionSelector.querySelector('div').onclick=()=>{
27 | collectionsList.style.display||="block";
28 | if(collectionsList.style.display==="block") collectionsList.style.display="none";
29 | else collectionsList.style.display="block";
30 | }
31 | for(let p of j.parts){
32 | p.link ||= p.value;
33 | p.type ||= p.contentType;
34 | collectionsList.innerHTML += `
${p.label} `;
35 | }
36 | let anchorList = collectionsList.querySelectorAll('A');
37 | for(let anchor of anchorList){
38 | anchor.onclick = (e)=>{
39 | e.preventDefault();
40 | let el = e.target;
41 | for(let a of anchorList){
42 | if(a==el) a.style.background=j.background;
43 | else a.style.background=j.highlight;
44 | }
45 | if(!j.size) {
46 | el.parentElement.style.display="none";
47 | collectionSelector.querySelector('DIV SPAN').innerHTML=el.innerHTML;
48 | }
49 | console.log(99,el.href,el.dataset.type,el.dataset.link)
50 | return j.onchange(el.innerHTML,el.href,el.dataset.type);
51 | }
52 | }
53 | if(j.size){
54 | if(j.size>j.parts.length) j.size=j.parts.length;
55 | j.size = (j.size*2)+1+"rem";
56 | collectionsList.style = `border:1px solid ${borderColor};border-top:none;height:${j.size}`;
57 | collectionsList.style.overflow="auto";
58 | collectionsList.style["max-height"]=j.size;
59 | // collectionsList.style["border-radius"]="0.4rem";
60 | }
61 | else {
62 | collectionsList.style=`border:1px solid ${borderColor};border-top:none;display:none`;
63 | // collectionSelector.style["border-radius"]="0.4rem";
64 | collectionSelector.style["margin-bottom"]="0.4rem";
65 | wrapper.appendChild(collectionSelector);
66 | }
67 | collectionsList.style["margin-bottom"]="0.4rem";
68 | wrapper.appendChild(collectionsList);
69 | return wrapper;
70 | }
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/view/reader.js:
--------------------------------------------------------------------------------
1 | export class FeedReader {
2 | async makeTopicSelector(options,targetSelector){
3 | }
4 | }
5 |
6 | :myFeedReader
7 |
8 | :topics [
9 | a ui:SparqlQuery ;
10 | ui:endpoint
;
11 | ui:query """
12 | PREFIX schema:
13 | PREFIX ui:
14 | SELECT DISTINCT ?label WHERE {
15 | ?x a ui:Feed; schema:about ?label .
16 | }
17 | """
18 | ] .
19 |
20 | :collections [
21 | a ui:SparqlQuery ;
22 | ui:endpoint ;
23 | ui:query """
24 | PREFIX schema:
25 | PREFIX ui:
26 | SELECT DISTINCT ?label ?href WHERE {
27 | ?x a ui:Feed;
28 | schema:about ${wantedTopic} ;
29 | ui:label ?label ;
30 | ui:href ?href .
31 | }
32 | """
33 | ] .
34 |
--------------------------------------------------------------------------------
/src/view/searchButton.js:
--------------------------------------------------------------------------------
1 | /*
2 |
29 |
30 | ⚲
31 |
32 | go
33 |
34 | */
35 | export async function searchButton(component){
36 |
37 | const searchBox = document.createElement('DIV');
38 | const targetElement = component.contentArea || document.body;
39 | const searchButton = document.createElement('BUTTON');
40 | const searchInput = document.createElement('INPUT');
41 |
42 | searchButton.title = component.title;
43 | searchBox.appendChild(searchInput);
44 | targetElement.appendChild(searchButton);
45 | targetElement.appendChild(searchBox);
46 |
47 | searchBox.style = "display:none;z-index:10;position:absolute;left:2.2rem; margin-top:-1rem; padding:0.4rem;background:brown;border-radius:0.4rem;"
48 |
49 | searchButton.innerHTML = component.label || "⚲"
50 | searchButton.style = "transform:rotate(315deg);font-size:1.75rem;";
51 | searchButton.addEventListener("click",async()=>{
52 | searchBox.style.display="block";
53 | });
54 |
55 | searchInput.style= "padding:0.5rem;width:60ch;border-radius:0.2rem";
56 | searchInput.placeholder = component.placeholder;
57 | searchInput.addEventListener("keypress",async(event)=>{
58 | if (event.key === "Enter") {
59 | searchBox.style.display="none";
60 | const term = searchInput.value;
61 | if(term) solidUI.util.show('SolidOSLink',term,'','#display')
62 | }
63 | });
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/view/selector.js:
--------------------------------------------------------------------------------
1 | import {optionSelector} from './optionSelector.js';
2 |
3 | /*
4 | containerSelector
5 | url
6 | targetSelector
7 | resourceOnChange
8 | collectionSize
9 | resourceSize
10 |
11 | podSelector({
12 | parts : [ {label,dataSource}, ... ],
13 | contentArea : display target of resource-picker
14 | displayArea : display target of resource
15 | collectionSize : integer, max height of selector element for collections
16 | resourceSize : integer, max height of selector element for resources
17 | onchange : action to occur when resource is selected
18 | });
19 |
20 | podSelector({
21 | parts : [ {label,dataSource}, ... ],
22 | contentArea : display target of resource-picker
23 | displayArea : display target of resource
24 | collectionSize : integer, max height of selector element for collections
25 | resourceSize : integer, max height of selector element for resources
26 | onchange : action to occur when resource is selected
27 | });
28 |
29 | */
30 | export async function podSelector(component){
31 | let pods = [];
32 | for(let pod of component.parts){
33 | pods.push({value:pod.dataSource,label:pod.label});
34 | }
35 | let podsOnchange = async (selectorElement)=>{
36 | let newHost = selectorElement.target.value;
37 | component.dataSource = newHost;
38 | return await resourceSelector(component);
39 | };
40 | pods = await selector(pods,podsOnchange,null,null,6,component);
41 | // pods.style.height="2rem";
42 | let container = pods[0] ?pods[0].value :pods;
43 |
44 | let hostEl = document.createElement('DIV');
45 | hostEl.style = "width:100% !important;text-align:right";
46 | hostEl.innerHTML = `
47 | Pod Explorer
48 |
49 | `;
50 | let targetArea = typeof component.contentArea==="string" ?document.querySelector(component.contentArea) :component.contentArea;
51 | targetArea.innerHTML="";
52 | targetArea.appendChild(hostEl);
53 | targetArea.appendChild(pods);
54 | component.dataSource = pods[0] ?pods[0].value :pods;
55 | let resources = await resourceSelector(component);
56 | }
57 |
58 | export async function resourceSelector(json){
59 | let url = json.dataSource || json.podLink;
60 | let targetSelector = json.contentArea;
61 | let collectionSize = json.collectionSize || 6;
62 | let resourceSize = json.resourceSize || 10;
63 | let resourceOnchange = json.onchange;
64 | if(typeof solidUI !="undefined") {
65 | resourceOnchange ||= async (label,link,cType)=>{
66 | await solidUI.showPage(null,null,{label,link,cType})
67 | };
68 | }
69 | const ldp = UI.rdf.Namespace("http://www.w3.org/ns/ldp#");
70 | if(!url) return "";
71 | let container = url.replace(/\/[^\/]*$/,'/'); // in case we get passed a resource
72 | let host = _host(container);
73 | const base = UI.rdf.sym(container);
74 | try {
75 | await UI.store.fetcher.load(base);
76 | }
77 | catch(e) {
78 | alert(e)
79 | }
80 | let files = UI.store.each(base,ldp("contains"),null,base);
81 | let resources = [];
82 | let containers=[];
83 | containers.push({value:base.uri,label:_pathname(base.uri)});
84 | for(let file of files.sort()){
85 | let name = file.value
86 | let contentType=_findContentType(file);
87 | if( _isHidden(name) ) continue;
88 | if(name.endsWith('/')) containers.push({value:name,label:_pathname(name),contentType:'text/turtle'});
89 | else resources.push({value:name,label:_pathname(name),contentType});
90 | }
91 | let parent = base.uri.replace(/\/$/,'').replace(/\/[^\/]*$/,'/');
92 | if(parent) {
93 | if(!parent.endsWith("//")) {
94 | containers.splice(1,0,{value:parent,label:"../"});
95 | }
96 | }
97 | let x = ()=>{};
98 | let containerOnchange = async (selectorElement,link)=>{
99 | let newContainer = link ?link :selectorElement.target.value;
100 | json.dataSource = newContainer;
101 | /*
102 | let thisContainerArea = document.querySelector('#PodSelector .containerSelector');
103 | */
104 | let newC = await resourceSelector(json);
105 | /*
106 | thisContainerArea.replaceWith(newC);
107 | return thisContainerArea;
108 | */
109 | let areaToWriteIn = document.querySelector('#PodSelector');
110 | if(areaToWriteIn){
111 | areaToWriteIn.innerHTML = "";
112 | areaToWriteIn.appendChild(newC);
113 | }
114 | return newC;
115 | };
116 | containers = await selector(containers,containerOnchange,url,null,collectionSize,json)
117 | resources = await selector(resources,resourceOnchange,url,null,resourceSize,json)
118 | containers.classList = ["containerSelector"];
119 | if(resources) resources.classList = ["resourceSelector"];
120 | if(targetSelector && typeof targetSelector==="string") targetSelector = document.querySelector(targetSelector);
121 | if(!targetSelector){
122 | let myid = json.label.replace(/\s/g,"_");
123 | targetSelector = document.getElementById(myid);
124 | }
125 | // if(targetSelector) div = targetSelector.querySelector("#PodSelector");
126 | let div=document.createElement('DIV');
127 | let hostEl = document.createElement('DIV');
128 | hostEl.style = "width:100% !important;text-align:right";
129 | hostEl.innerHTML = `
130 | Pod Explorer
131 |
132 | `;
133 | div.innerHTML = "";
134 | div.appendChild(hostEl);
135 | div.id = "PodSelector"
136 | if(containers) div.appendChild(containers);
137 | if(resources) div.appendChild(resources);
138 | /*
139 | let anchor = targetSelector.querySelector('A')
140 | if(anchor)anchor.addEventListener('click',(e)=>{
141 | e.preventDefault();
142 | solidUI.showPage(e,{link:container,displayArea:json.displayArea});
143 | });
144 | */
145 | return div;
146 | }
147 |
148 | function _findContentType(fileNode){
149 | const isa = UI.rdf.sym("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
150 | let types = UI.store.each(fileNode,isa).map((s)=>{return s.value});
151 | for(let type of types){
152 | if(type.match(/http:\/\/www.w3.org\/ns\/iana\/media-types/))
153 | return type.replace(/http:\/\/www.w3.org\/ns\/iana\/media-types\//,'').replace(/\#Resource/,'');
154 | }
155 | }
156 |
157 | function _isHidden(path){
158 | if(!path) return true;
159 | let name = new URL(path);
160 | name = name.pathname;
161 | name= name.endsWith('/') ?name.replace(/^\//,'') :name.replace(/.*\//,'');
162 | if(name.startsWith('.') ) return true;
163 | if(name.match(/\/\./) ) return true;
164 | if(name.endsWith('~') ) return true;
165 | }
166 | function _pathname(path){
167 | try{
168 | let p = new URL(path);
169 | return p.pathname
170 | }
171 | catch(e){console.log(path,e); return path };
172 | }
173 | function _host(path){
174 | try{
175 | let p = new URL(path);
176 | return p.host
177 | }
178 | catch(e){console.log(path,e); return path };
179 | }
180 | function _origin(path){
181 | try{
182 | let p = new URL(path);
183 | return p.origin
184 | }
185 | catch(e){console.log(path,e); return path };
186 | }
187 |
188 |
189 | /*
190 | @paramoptions : an array of arrays [ [value1,label1], [value2,label2] ]
191 | onchange : callback function when item selected
192 | selected : value to select (from options)
193 | targetSelector : an optional css selector e.g. "#foo .bar" where output should be placed
194 | size : optional integer size of selector
195 | returns an HTML select element
196 | */
197 | export function selector(options,onchange,selected,targetSelector,size,o){
198 |
199 | function mungeLabel(label){
200 | if(!label) return "";
201 | label = decodeURI(label);
202 | if(!label.endsWith("/")) label = label.replace(/.*\//,'')
203 | return label || "/";
204 | }
205 | //...
206 | for(let o of options){
207 | o.label = mungeLabel(o.label);
208 | }
209 | return optionSelector({
210 | parts : options,
211 | onchange,
212 | size,
213 | });
214 | //...
215 |
216 | function addAttributes(option,optionEl){
217 | if(Object.keys(option).length>2){
218 | for(let k of Object.keys(option)){
219 | if(k==="value"||k==="label")continue;
220 | optionEl.dataset ||= {};
221 | optionEl.dataset[k] = option[k];
222 | }
223 | }
224 | return optionEl;
225 | }
226 |
227 | let computedSize = options.length;
228 | size ||= 0;
229 | size = computedSize <= size ?computedSize :size;
230 | size ||=1;
231 | /*
232 | if(size ===1) {
233 | let button = document.createElement('BUTTON');
234 | button.value = options[0].value;
235 | button.innerHTML = mungeLabel(options[0].label);
236 | button.addEventListener('click',(e)=>{
237 | onchange(e)
238 | // onchange(e.target)
239 | })
240 | return button;
241 | }
242 | */
243 | let selectEl = document.createElement('SELECT');
244 | let optgroupEl = document.createElement('OPTGROUP');
245 | optgroupEl.style.margin=0;
246 | optgroupEl.style.padding=0;
247 | // selectEl.appendChild(optgroupEl);
248 | selectEl.style.background = o.darkBackground;
249 | selectEl.style["margin-top"] = "1rem";
250 | for(let option of options){
251 | let value,label;
252 | if(typeof option==="string") value = label = option;
253 | else {
254 | value = option.value
255 | label = option.label || option.value
256 | }
257 | if(!label || !option) continue;
258 | label=mungeLabel(label);
259 | // label = decodeURI(label);
260 | // if(!label.endsWith("/"))
261 | // label = label.replace(/.*\//,'')
262 | // label ||= "/";
263 | let optionEl = document.createElement('OPTION');
264 | optionEl.style["font-size"]="large";
265 | // optionEl.style = "padding:0.25em;";
266 | optionEl.style.background = o.background || solidUI.buttonBackground;
267 | optionEl.style.color = o.color || solidUI.buttonColor;
268 | optionEl.value = value;
269 | optionEl.title = value+"\n"+(option.contentType||"");
270 | optionEl.dataset ||= {};
271 | optionEl.dataset.contenttype=option.contentType||"";
272 | optionEl.innerHTML = label;
273 | optionEl = addAttributes(option,optionEl);
274 | /*
275 | if(Object.keys(option).length>2){
276 | for(let k of Object.keys(option)){
277 | if(k==="value"||k==="label")continue;
278 | optionEl.dataset ||= {};
279 | optionEl.dataset[k] = option[k];
280 | }
281 | }
282 | */
283 | //optgroupEl.appendChild(optionEl);
284 | selectEl.appendChild(optionEl);
285 | }
286 |
287 | /* HIGHLIGHT SELECTED */
288 | if(selected) selectEl.value = selected;
289 | // selectEl.value ||= selectEl.childNodes[0].value;
290 |
291 | // selectEl.addEventListener('click',async(e)=>{
292 | // onchange(e.target)
293 | // })
294 | selectEl.addEventListener('change',async(e)=>{
295 | onchange(e)
296 | // onchange(e.target)
297 | })
298 | selectEl.size = size
299 | selectEl.style.width="100%";
300 | if(targetSelector) {
301 | let targetEl = document.querySelector(targetSelector)
302 | targetEl.innerHTML = ""
303 | targetEl.appendChild(selectEl);
304 | }
305 | return selectEl;
306 | }
307 |
308 |
--------------------------------------------------------------------------------
/src/view/selector.new.js:
--------------------------------------------------------------------------------
1 | /*
2 | containerSelector
3 | url
4 | targetSelector
5 | resourceOnChange
6 | collectionSize
7 | resourceSize
8 |
9 | podSelector({
10 | parts : [ {label,dataSource}, ... ],
11 | contentArea : display target of resource-picker
12 | displayArea : display target of resource
13 | collectionSize : integer, max height of selector element for collections
14 | resourceSize : integer, max height of selector element for resources
15 | onchange : action to occur when resource is selected
16 | });
17 |
18 | podSelector({
19 | parts : [ {label,dataSource}, ... ],
20 | contentArea : display target of resource-picker
21 | displayArea : display target of resource
22 | collectionSize : integer, max height of selector element for collections
23 | resourceSize : integer, max height of selector element for resources
24 | onchange : action to occur when resource is selected
25 | });
26 |
27 | */
28 | export async function podSelector(component){
29 | let pods = [];
30 | for(let pod of component.parts){
31 | pods.push({value:pod.dataSource,label:pod.label});
32 | }
33 | let podsOnchange = async (selectorElement)=>{
34 | let newHost = selectorElement.target.value;
35 | component.dataSource = newHost;
36 | return await resourceSelector(component);
37 | };
38 | pods = await selector(pods,podsOnchange,null,null,6,component);
39 | // pods.style.height="2rem";
40 | let container = pods[0].value;
41 | /*
42 | let hostEl = document.createElement('DIV');
43 | hostEl.style = "width:100% !important;text-align:right";
44 | hostEl.innerHTML = `
45 | Pod Explorer
46 |
47 | `;
48 | */
49 | let targetArea = typeof component.contentArea==="string" ?document.querySelector(component.contentArea) :component.contentArea;
50 | console.log(78,targetArea);
51 | targetArea.innerHTML="";
52 | // targetArea.appendChild(hostEl);
53 | targetArea.appendChild(pods);
54 | component.dataSource = pods[0].value;
55 | let resources = await resourceSelector(component);
56 | }
57 |
58 | export async function resourceSelector(json){
59 | let url = json.dataSource || json.podLink;
60 | let targetSelector = json.contentArea;
61 | let collectionSize = json.collectionSize || 6;
62 | let resourceSize = json.resourceSize || 10;
63 | let resourceOnchange = json.onchange;
64 | if(typeof solidUI !="undefined") resourceOnchange ||= async (e)=>{await solidUI.showPage(e,json)};
65 | const ldp = UI.rdf.Namespace("http://www.w3.org/ns/ldp#");
66 | if(!url) return "";
67 | let container = url.replace(/\/[^\/]*$/,'/'); // in case we get passed a resource
68 | let host = _host(container);
69 | const base = UI.rdf.sym(container);
70 | await UI.store.fetcher.load(base);
71 | let files = UI.store.each(base,ldp("contains"),null,base);
72 | let resources = [];
73 | let containers=[];
74 | containers.push({value:base.uri,label:_pathname(base.uri)});
75 | for(let file of files.sort()){
76 | let name = file.value
77 | let contentType=_findContentType(file);
78 | if( _isHidden(name) ) continue;
79 | if(name.endsWith('/')) containers.push({value:name,label:_pathname(name),contentType});
80 | else resources.push({value:name,label:_pathname(name),contentType});
81 | }
82 | let parent = base.uri.replace(/\/$/,'').replace(/\/[^\/]*$/,'/');
83 | if(parent) {
84 | if(!parent.endsWith("//")) {
85 | containers.splice(1,0,{value:parent,label:"../"});
86 | }
87 | }
88 | let x = ()=>{};
89 | let containerOnchange = async (selectorElement)=>{
90 | let newContainer = selectorElement.target.value;
91 | json.dataSource = newContainer;
92 | let thisContainerArea = document.querySelector('#PodSelector .containerSelector');
93 | let newC = await resourceSelector(json);
94 | thisContainerArea.replaceWith(newC);
95 | console.log(88,newC)
96 | return thisContainerArea;
97 | };
98 | containers = await selector(containers,containerOnchange,url,null,collectionSize,json)
99 | resources = await selector(resources,resourceOnchange,url,null,resourceSize,json)
100 | containers.classList = ["containerSelector"];
101 | if(resources) resources.classList = ["resourceSelector"];
102 | if(targetSelector && typeof targetSelector==="string") targetSelector = document.querySelector(targetSelector);
103 | if(!targetSelector){
104 | let myid = json.label.replace(/\s/g,"_");
105 | targetSelector = document.getElementById(myid);
106 | }
107 | // if(targetSelector) div = targetSelector.querySelector("#PodSelector");
108 | let div=document.createElement('DIV');
109 | div.innerHTML = "";
110 | div.id = "PodSelector"
111 | if(containers) div.appendChild(containers);
112 | if(resources) div.appendChild(resources);
113 | /*
114 | let anchor = targetSelector.querySelector('A')
115 | if(anchor)anchor.addEventListener('click',(e)=>{
116 | e.preventDefault();
117 | solidUI.showPage(e,{link:container,displayArea:json.displayArea});
118 | });
119 | */
120 | return div;
121 | }
122 |
123 | function _findContentType(fileNode){
124 | const isa = UI.rdf.sym("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
125 | let types = UI.store.each(fileNode,isa).map((s)=>{return s.value});
126 | for(let type of types){
127 | if(type.match(/http:\/\/www.w3.org\/ns\/iana\/media-types/))
128 | return type.replace(/http:\/\/www.w3.org\/ns\/iana\/media-types\//,'').replace(/\#Resource/,'');
129 | }
130 | }
131 |
132 | function _isHidden(path){
133 | if(!path) return true;
134 | let name = new URL(path);
135 | name = name.pathname;
136 | name= name.endsWith('/') ?name.replace(/^\//,'') :name.replace(/.*\//,'');
137 | if(name.startsWith('.') ) return true;
138 | if(name.endsWith('~') ) return true;
139 | }
140 | function _pathname(path){
141 | try{
142 | let p = new URL(path);
143 | return p.pathname
144 | }
145 | catch(e){console.log(path,e); return path };
146 | }
147 | function _host(path){
148 | try{
149 | let p = new URL(path);
150 | return p.host
151 | }
152 | catch(e){console.log(path,e); return path };
153 | }
154 | function _origin(path){
155 | try{
156 | let p = new URL(path);
157 | return p.origin
158 | }
159 | catch(e){console.log(path,e); return path };
160 | }
161 |
162 |
163 | /*
164 | @paramoptions : an array of arrays [ [value1,label1], [value2,label2] ]
165 | onchange : callback function when item selected
166 | selected : value to select (from options)
167 | targetSelector : an optional css selector e.g. "#foo .bar" where output should be placed
168 | size : optional integer size of selector
169 | returns an HTML select element
170 | */
171 | export function selector(options,onchange,selected,targetSelector,size,o){
172 |
173 | function mungeLabel(label){
174 | if(!label) return "";
175 | label = decodeURI(label);
176 | if(!label.endsWith("/")) label = label.replace(/.*\//,'')
177 | return label || "/";
178 | }
179 | function addAttributes(option,optionEl){
180 | if(Object.keys(option).length>2){
181 | for(let k of Object.keys(option)){
182 | if(k==="value"||k==="label")continue;
183 | optionEl.dataset ||= {};
184 | optionEl.dataset[k] = option[k];
185 | }
186 | }
187 | return optionEl;
188 | }
189 |
190 | let computedSize = options.length;
191 | size ||= 0;
192 | size = computedSize <= size ?computedSize :size;
193 | size ||=1;
194 | /*
195 | if(size ===1) {
196 | let button = document.createElement('BUTTON');
197 | button.value = options[0].value;
198 | button.innerHTML = mungeLabel(options[0].label);
199 | button.addEventListener('click',(e)=>{
200 | onchange(e)
201 | // onchange(e.target)
202 | })
203 | return button;
204 | }
205 | */
206 | let selectEl = document.createElement('SELECT');
207 | let optgroupEl = document.createElement('OPTGROUP');
208 | optgroupEl.style.margin=0;
209 | optgroupEl.style.padding=0;
210 | // selectEl.appendChild(optgroupEl);
211 | selectEl.style.background = o.darkBackground;
212 | selectEl.style["margin-top"] = "1rem";
213 | for(let option of options){
214 | let value,label;
215 | if(typeof option==="string") value = label = option;
216 | else {
217 | value = option.value
218 | label = option.label || option.value
219 | }
220 | if(!label || !option) continue;
221 | label=mungeLabel(label);
222 | // label = decodeURI(label);
223 | // if(!label.endsWith("/"))
224 | // label = label.replace(/.*\//,'')
225 | // label ||= "/";
226 | let optionEl = document.createElement('OPTION');
227 | optionEl.style["font-size"]="18px";
228 | // optionEl.style = "padding:0.25em;";
229 | optionEl.style.background = o.lightBackground;
230 | optionEl.style.color = o.lightBackground;
231 | optionEl.value = value;
232 | optionEl.title = value+"\n"+(option.contentType||"");
233 | optionEl.dataset ||= {};
234 | optionEl.dataset.contenttype=option.contentType||"";
235 | optionEl.innerHTML = label;
236 | optionEl = addAttributes(option,optionEl);
237 | /*
238 | if(Object.keys(option).length>2){
239 | for(let k of Object.keys(option)){
240 | if(k==="value"||k==="label")continue;
241 | optionEl.dataset ||= {};
242 | optionEl.dataset[k] = option[k];
243 | }
244 | }
245 | */
246 | //optgroupEl.appendChild(optionEl);
247 | selectEl.appendChild(optionEl);
248 | }
249 |
250 | /* HIGHLIGHT SELECTED */
251 | if(selected) selectEl.value = selected;
252 | // selectEl.value ||= selectEl.childNodes[0].value;
253 |
254 | // selectEl.addEventListener('click',async(e)=>{
255 | // onchange(e.target)
256 | // })
257 | selectEl.addEventListener('change',async(e)=>{
258 | onchange(e)
259 | // onchange(e.target)
260 | })
261 | selectEl.size = size
262 | selectEl.style.width="100%";
263 | if(targetSelector) {
264 | let targetEl = document.querySelector(targetSelector)
265 | targetEl.innerHTML = ""
266 | targetEl.appendChild(selectEl);
267 | }
268 | return selectEl;
269 | }
270 |
271 |
--------------------------------------------------------------------------------
/src/view/selector.org.js:
--------------------------------------------------------------------------------
1 | /* containerSelector
2 | url
3 | targetSelector
4 | resourceOnChange
5 | collectionSize
6 | resourceSize
7 | */
8 | export async function containerSelector(json){
9 | let url = json.dataSource;
10 | let targetSelector = json.contentArea;
11 | let collectionSize = json.collectionSize || 6;
12 | let resourceSize = json.resourceSize || 12;
13 | let resourceOnchange = async (e)=>{await solidUI.showPage(e,json)};
14 | const ldp = UI.rdf.Namespace("http://www.w3.org/ns/ldp#");
15 | if(!url) return "";
16 | let container = url.replace(/\/[^\/]*$/,'/'); // in case we get passed a resource
17 | let host = _host(container);
18 | const base = UI.rdf.sym(container);
19 | await UI.store.fetcher.load(base);
20 | let files = UI.store.each(base,ldp("contains"),null,base);
21 | let resources = [];
22 | let containers=[];
23 | containers.push({value:base.uri,label:_pathname(base.uri)});
24 | for(let file of files.sort()){
25 | let name = file.value
26 | let contentType=_findContentType(file);
27 | if( _isHidden(name) ) continue;
28 | if(name.endsWith('/')) containers.push({value:name,label:_pathname(name),contentType});
29 | else resources.push({value:name,label:_pathname(name),contentType});
30 | }
31 | let parent = base.uri.replace(/\/$/,'').replace(/\/[^\/]*$/,'/');
32 | if(parent) {
33 | if(!parent.endsWith("//")) {
34 | containers.splice(1,0,{value:parent,label:"../"});
35 | }
36 | }
37 | let x = ()=>{};
38 | let containerOnchange = async (selectorElement)=>{
39 | let newContainer = selectorElement.target.value;
40 | json.dataSource = newContainer;
41 | return await containerSelector(json);
42 | };
43 | containers = await selector(containers,containerOnchange,url,null,collectionSize)
44 | resources = await selector(resources,resourceOnchange,url,null,resourceSize)
45 | containers.classList = ["containerSelector"];
46 | if(resources) resources.classList = ["resourceSelector"];
47 | if(targetSelector && typeof targetSelector==="string") targetSelector = document.querySelector(targetSelector);
48 | let div = targetSelector ?targetSelector :document.createElement('DIV');
49 | let hostEl = document.createElement('DIV');
50 | hostEl.style = "width:100% !important;text-align:right";
51 | hostEl.innerHTML = `
52 | ${host}
53 |
54 | `;
55 | hostEl.querySelector('A').addEventListener('click',(e)=>{
56 | //alert(e)
57 | e.preventDefault();
58 | solidUI.showPage(e,{link:container,displayArea:json.displayArea});
59 | });
60 | div.innerHTML = "";
61 | if(hostEl) div.appendChild(hostEl);
62 | if(containers) div.appendChild(containers);
63 | if(resources) div.appendChild(resources);
64 | return div;
65 | }
66 |
67 | function _findContentType(fileNode){
68 | const isa = UI.rdf.sym("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
69 | let types = UI.store.each(fileNode,isa).map((s)=>{return s.value});
70 | for(let type of types){
71 | if(type.match(/http:\/\/www.w3.org\/ns\/iana\/media-types/))
72 | return type.replace(/http:\/\/www.w3.org\/ns\/iana\/media-types\//,'').replace(/\#Resource/,'');
73 | }
74 | }
75 |
76 | function _isHidden(path){
77 | if(!path) return true;
78 | let name = new URL(path);
79 | name = name.pathname;
80 | name= name.endsWith('/') ?name.replace(/^\//,'') :name.replace(/.*\//,'');
81 | if(name.startsWith('.') ) return true;
82 | if(name.endsWith('~') ) return true;
83 | }
84 | function _pathname(path){
85 | try{
86 | let p = new URL(path);
87 | return p.pathname
88 | }
89 | catch(e){console.log(path,e); return path };
90 | }
91 | function _host(path){
92 | try{
93 | let p = new URL(path);
94 | return p.host
95 | }
96 | catch(e){console.log(path,e); return path };
97 | }
98 | function _origin(path){
99 | try{
100 | let p = new URL(path);
101 | return p.origin
102 | }
103 | catch(e){console.log(path,e); return path };
104 | }
105 |
106 |
107 | /*
108 | @paramoptions : an array of arrays [ [value1,label1], [value2,label2] ]
109 | onchange : callback function when item selected
110 | selected : value to select (from options)
111 | targetSelector : an optional css selector e.g. "#foo .bar" where output should be placed
112 | size : optional integer size of selector
113 | returns an HTML select element
114 | */
115 | export function selector(options,onchange,selected,targetSelector,size){
116 |
117 | function mungeLabel(label){
118 | if(!label) return "";
119 | label = decodeURI(label);
120 | if(!label.endsWith("/")) label = label.replace(/.*\//,'')
121 | return label || "/";
122 | }
123 | function addAttributes(option,optionEl){
124 | if(Object.keys(option).length>2){
125 | for(let k of Object.keys(option)){
126 | if(k==="value"||k==="label")continue;
127 | optionEl.dataset ||= {};
128 | optionEl.dataset[k] = option[k];
129 | }
130 | }
131 | return optionEl;
132 | }
133 |
134 |
135 |
136 | let computedSize = options.length;
137 | size ||= 0;
138 | size = computedSize <= size ?computedSize :size;
139 | if(size <1) return;
140 | if(size ===1) {
141 | let button = document.createElement('BUTTON');
142 | button.value = options[0].value;
143 | button.innerHTML = mungeLabel(options[0].label);
144 | button.addEventListener('click',(e)=>{
145 | onchange(e)
146 | // onchange(e.target)
147 | })
148 | return button;
149 | }
150 | let selectEl = document.createElement('SELECT');
151 | for(let option of options){
152 | let value,label;
153 | if(typeof option==="string") value = label = option;
154 | else {
155 | value = option.value
156 | label = option.label || option.value
157 | }
158 | if(!label || !option) continue;
159 | label=mungeLabel(label);
160 | // label = decodeURI(label);
161 | // if(!label.endsWith("/"))
162 | // label = label.replace(/.*\//,'')
163 | // label ||= "/";
164 | let optionEl = document.createElement('OPTION');
165 | optionEl.value = value;
166 | optionEl.title = value+"\n"+(option.contentType||"");
167 | optionEl.dataset ||= {};
168 | optionEl.dataset.contenttype=option.contentType||"";
169 | optionEl.innerHTML = label;
170 | optionEl.style = "padding:0.25em;";
171 | optionEl = addAttributes(option,optionEl);
172 | /*
173 | if(Object.keys(option).length>2){
174 | for(let k of Object.keys(option)){
175 | if(k==="value"||k==="label")continue;
176 | optionEl.dataset ||= {};
177 | optionEl.dataset[k] = option[k];
178 | }
179 | }
180 | */
181 | selectEl.appendChild(optionEl);
182 | }
183 |
184 | /* HIGHLIGHT SELECTED */
185 | if(selected) selectEl.value = selected;
186 | // selectEl.value ||= selectEl.childNodes[0].value;
187 |
188 | // selectEl.addEventListener('click',async(e)=>{
189 | // onchange(e.target)
190 | // })
191 | selectEl.addEventListener('change',async(e)=>{
192 | onchange(e)
193 | // onchange(e.target)
194 | })
195 | selectEl.size = size
196 | selectEl.style="padding:0.5em;width:100%"
197 | if(targetSelector) {
198 | let targetEl = document.querySelector(targetSelector)
199 | targetEl.innerHTML = ""
200 | targetEl.appendChild(selectEl);
201 | }
202 | return selectEl;
203 | }
204 |
205 |
--------------------------------------------------------------------------------
/src/view/selectorPanel.js:
--------------------------------------------------------------------------------
1 | /*
2 | color // a ui:Color for text of the selector
3 | background // a ui:Color for the background of the selector
4 | highlight // a ui:Color for the selector options background
5 | size // the number of options to show
6 | parts // an array of options
7 | dataSource // a component address that yields an array of options
8 | onchange // action to take on selection
9 | */
10 | export function optionSelector(j) {
11 | const hasSuic = typeof solidUI !="undefined";
12 | j.color ||= hasSuic ?solidUI.menuColor :"#000000";
13 | j.background ||= hasSuic ?solidUI.menuBackground : "#c0c0c0";
14 | j.highlight ||= hasSuic ?solidUI.menuHighlight : "#909090";
15 | j.size ||= hasSuic ?solidUI.selectorSize :0;
16 | const borderColor = j.color;
17 | const wrapper = document.createElement('DIV');
18 | let collectionSelector = document.createElement('DIV');
19 | collectionSelector.style = `border:1px solid ${borderColor};border-bottom:none`;
20 | collectionSelector.style.background=j.background;
21 | collectionSelector.style.color= j.color;
22 | j.parts ||= j.dataSource.parts;
23 | const firstOption = j.label || (j.parts[0]).label || j.parts[0];
24 | collectionSelector.innerHTML = `${firstOption} ⌄
`;
25 | let collectionsList = document.createElement('DIV');
26 | collectionSelector.querySelector('div').onclick=()=>{
27 | collectionsList.style.display||="block";
28 | if(collectionsList.style.display==="block") collectionsList.style.display="none";
29 | else collectionsList.style.display="block";
30 | }
31 | for(let p of j.parts){
32 | collectionsList.innerHTML += `${p.label} `;
33 | }
34 | let anchorList = collectionsList.querySelectorAll('A');
35 | for(let anchor of anchorList){
36 | anchor.onclick = (e)=>{
37 | e.preventDefault();
38 | let el = e.target;
39 | for(let a of anchorList){
40 | if(a==el) a.style.background=j.background;
41 | else a.style.background=j.highlight;
42 | }
43 | if(!j.size) {
44 | el.parentElement.style.display="none";
45 | collectionSelector.querySelector('DIV SPAN').innerHTML=el.innerHTML;
46 | }
47 | console.log(99,el.href,el.dataset.type,el.dataset.link)
48 | return j.onchange(el.innerHTML,el.href,el.dataset.type);
49 | }
50 | }
51 | if(j.size){
52 | if(j.size>j.parts.length) j.size=j.parts.length;
53 | j.size = (j.size*2)+1+"rem";
54 | collectionsList.style = `border:1px solid ${borderColor};border-top:none;height:${j.size}`;
55 | collectionsList.style.overflow="auto";
56 | collectionsList.style["max-height"]=j.size;
57 | collectionsList.style["border-radius"]="0.4rem";
58 | }
59 | else {
60 | collectionsList.style=`border:1px solid ${borderColor};border-top:none;display:none`;
61 | collectionSelector.style["border-radius"]="0.4rem";
62 | wrapper.appendChild(collectionSelector);
63 | }
64 | wrapper.appendChild(collectionsList);
65 | return wrapper;
66 | }
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/view/slideshow.js:
--------------------------------------------------------------------------------
1 | class Slideshow {
2 | render(component,results) {
3 | const height = component.height || "320px";
4 | const width = component.width || "480px";
5 | const slideshow = solidUI.createElement('DIV','','',`height:${height};width:${width};text-align:center`);
6 | let i = 0;
7 | for(let row of results){
8 | let slide = solidUI.createElement('DIV','mySlides','');
9 | let img = solidUI.createElement('IMG','','',`height:${height};max-width:${width}`)
10 | const label = solidUI.createElement('DIV','',row.label)
11 | img.src = row.image;
12 | if(i) slide.style.display="none";
13 | i++;
14 | slide.appendChild(img);
15 | slide.appendChild(label);
16 | slideshow.appendChild(slide);
17 | }
18 | const prev = solidUI.createElement('A','','❮',"cursor:pointer");
19 | const next = solidUI.createElement('A','','❯',"cursor:pointer");
20 | const play = solidUI.createElement('A','','\u23f5',"font-size:2rem;font-weight:bold;cursor:pointer;");
21 | const pause = solidUI.createElement('A','','\u23f8','font-size:2rem;font-weight:bold;cursor:pointer;display:none;');
22 | // prev.onclick=(event)=>{changeSlide(event,-1)};
23 | // next.onclick=(event)=>{changeSlide(event,1)};
24 | play.onclick=(event)=>{playSlides(event,pause,play)};
25 | play.title="play slides";
26 | pause.title="pause slides";
27 | pause.onclick=(event)=>{pauseSlides(event,pause,play)};
28 | // slideshow.appendChild(prev);
29 | slideshow.appendChild(play);
30 | slideshow.appendChild(pause);
31 | // slideshow.appendChild(next);
32 | return slideshow
33 | }
34 | } // end class Slideshow
35 |
36 | var slideIndex = 1;
37 | var paused = false;
38 |
39 | function changeSlide(event,n) {
40 | paused = true;
41 | showSlidesManual(event,slideIndex += n);
42 | }
43 |
44 | function showSlidesManual(event,n) {
45 | var i;
46 | var slides = document.querySelectorAll(".mySlides");
47 | if (n > slides.length) {slideIndex = 1}
48 | if (n < 1) {slideIndex = slides.length}
49 | for (i = 0; i < slides.length; i++) {
50 | slides[i].style.display = "none";
51 | }
52 | slides[slideIndex-1].style.display = "block";
53 | }
54 | function pauseSlides(event,pause,play) {
55 | paused=true;
56 | play.style.display="block";
57 | pause.style.display="none";
58 | }
59 | function playSlides(event,pause,play){
60 | play.style.display="none";
61 | pause.style.display="block";
62 | paused = false;
63 | showSlides();
64 | }
65 |
66 | function showSlides() {
67 | var i;
68 | var slides = document.getElementsByClassName("mySlides");
69 | for (i = 0; i < slides.length; i++) {
70 | slides[i].style.display = "none";
71 | }
72 | slideIndex++;
73 | if (slideIndex > slides.length) {slideIndex = 1}
74 | slides[slideIndex-1].style.display = "block";
75 | if(!paused)
76 | setTimeout(showSlides, 2000); // Change image every 2 seconds
77 | }
--------------------------------------------------------------------------------
/src/view/solidOSpage.js:
--------------------------------------------------------------------------------
1 | export class solidOSpage {
2 | render(json){
3 | let tabulator = document.getElementById('suicTabulator')
4 | if(!window.outliner) {
5 | tabulator.style= `
6 | display: none; /* Hidden by default */
7 | position: fixed; /* Stay in place */
8 | z-index: 1; /* Sit on top */
9 | left: 0;
10 | top: 10vh;
11 | height: 90vh; /* Full height */
12 | width: 100%; /* Full width */
13 | overflow: auto; /* Enable scroll if needed */
14 | background-color: rgb(0,0,0); /* Fallback color */
15 | background-color: rgba(0,0,0,0.2); /* Black w/ opacity */
16 | `
17 | window.outliner = panes.getOutliner(document);
18 | }
19 | window.outliner.GotoSubject(window.kb.sym(url),true,undefined,true);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/view/table.js:
--------------------------------------------------------------------------------
1 | export class Table {
2 | render(options) {
3 | let results = options.parts;
4 | if(!results || !results.length) {
5 | console.log("No results!");
6 | return document.createElement('SPAN');
7 | }
8 | if(options.sortOn) {
9 | // results.sort((a,b)=> a[options.sortOn] - b[options.sortOn] )
10 | results = results.reverse();
11 | }
12 | let table = document.createElement('TABLE');
13 | let columnHeaders = Object.keys(results[0]);
14 | let headerRow = document.createElement('TR');
15 | for(let c of columnHeaders){
16 | let cell = document.createElement('TH');
17 | cell.innerHTML = c;
18 | cell.style.border="1px solid black";
19 | cell.style.padding="0.5em";
20 | cell.style.background=options.unselBackground;
21 | cell.style.color=options.unselColor;
22 | headerRow.appendChild(cell);
23 | }
24 | table.appendChild(headerRow);
25 | for(let row of results){
26 | let rowElement = document.createElement('TR');
27 | for(let col of columnHeaders){
28 | if(options.cleanNodes){
29 | row[col] = row[col].replace(/.*\#/,'').replace(/.*\//,'');
30 | }
31 | let cell = document.createElement('TD');
32 | cell.innerHTML = row[col];
33 | cell.style.border="1px solid black";
34 | cell.style.padding="0.5em";
35 | cell.style.backgroundColor=options.background;
36 | cell.style.color=options.color;
37 | rowElement.appendChild(cell);
38 | }
39 | table.appendChild(rowElement);
40 | }
41 | table.style.borderCollapse="collapse";
42 | return table;
43 | }
44 | }
45 | // ENDS
46 |
--------------------------------------------------------------------------------
/src/view/tabs-old.js:
--------------------------------------------------------------------------------
1 | export class Tabs {
2 | async render(solidUI,json) {
3 | let parts = json.parts
4 | const tabs = solidUI.createElement('DIV','solid-uic-tabs');
5 | if(json.style) tabs.style = json.style;
6 | const nav = solidUI.createElement('NAV');
7 | if(json.orientation==="vertical")
8 | nav.style.textAlign = "right";
9 | else
10 | nav.style.textAlign = json.position;
11 | let mainDisplay = solidUI.createElement( 'DIV' );
12 | mainDisplay.style.backgroundColor = solidUI.pageBackground || json.background;
13 | mainDisplay.style.color = solidUI.pageColor || json.color;
14 | let r = 0;
15 | if(!parts.length) parts = [parts];
16 | for(let row of parts){
17 | r++;
18 | let rowhead = solidUI.createElement( 'BUTTON',r,row.label );
19 | rowhead.style.backgroundColor = solidUI.menuBackgroundColor || json.background;
20 | rowhead.style.color = solidUI.menuColor || json.color;
21 | rowhead.style.padding="0.5em";
22 | // rowhead.style.border="1px solid grey";
23 | rowhead.style.border="none";
24 | rowhead.style.cursor = "pointer";
25 | solidUI.currentElement = json.contentArea;
26 | //JZ let rc = row.dataSource ? await solidUI.processComponentSubject(row.dataSource) : row.content;
27 | rowhead.setAttribute("name",row.dataSource);
28 | let rowContent = solidUI.createElement( 'DIV',r );
29 | if(row.content) rowContent.appendChild(row.content);
30 | rowContent.style.padding="0.75em";
31 | // if(json.orientation==="horizontal") rowContent.style.border="1px solid grey";
32 | rowContent.style.display = "none";
33 | if(row.type==="SolidOSLink"){
34 | let id = `tab-${r}-outline`;
35 | rowContent.innerHTML = `
36 |
40 | `;
41 | let subject = window.kb.sym(row.href);
42 | let targetArea = rowContent.querySelector('#'+id);
43 | targetArea.style="display:table-row;background-color:c0c0c0"
44 | window.outliner.GotoSubject(subject,true,undefined,true,undefined,targetArea);
45 | }
46 | rowhead.onclick = (e)=>{
47 | e.preventDefault();
48 | alert(44,e.target.getAttribute('name'));
49 | console.log(44,e.target);
50 | let items = tabs.querySelector('DIV').children;
51 | for(let i of items) {
52 | i.style.display="none";
53 | }
54 | for(let n of nav.children) {
55 | n.style.backgroundColor = solidUI.menuBackground || json.background;
56 | n.style.color = solidUI.menuColor || json.color;
57 | }
58 | rowhead.style.backgroundColor = solidUI.menuColor || json.color;
59 | rowhead.style.color = solidUI.menuBackground || json.background;
60 | rowContent.style.display = "block";
61 | }
62 | nav.appendChild(rowhead);
63 | mainDisplay.appendChild(rowContent);
64 | if(json.orientation==="vertical"){
65 | rowhead.style.display="block";
66 | rowhead.style.marginBottom = "0.5em";
67 | rowhead.style.width="100%"
68 | tabs.style.width="100%";
69 | tabs.style.height="100%";
70 | tabs.style.display = "table-row";
71 | nav.style.display = "table-cell";
72 | mainDisplay.style.display = "table-cell";
73 | mainDisplay.style.display="block"
74 | mainDisplay.style.height = "100%";
75 | rowContent.style.height = "100%";
76 | }
77 | else {
78 | rowhead.style.marginRight = "0.25em";
79 | rowhead.style.borderBottom = "none";
80 | }
81 | }
82 | tabs.appendChild(nav);
83 | const closeButton = document.createElement('SPAN');
84 | closeButton.style = `
85 | color:red;
86 | text-align:right;
87 | position:absolute;
88 | top:0.25rem;
89 | right:0.25rem;
90 | font-size: 2rem;
91 | font-weight: bold;
92 | cursor:pointer
93 | `;
94 | closeButton.addEventListener('click',(e)=>{
95 | e.preventDefault();
96 | e.target.parentElement.style.display="none";
97 | });
98 | closeButton.innerHTML = "×";
99 |
100 | tabs.appendChild(closeButton);
101 | tabs.appendChild(mainDisplay);
102 | console.log(99,json);
103 | await solidUI.simulateClick(tabs.querySelector('BUTTON'))
104 | return tabs
105 | //JZ return await solidUI.initInternal(tabs);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/view/tabs.js:
--------------------------------------------------------------------------------
1 | export async function tabSet(options) {
2 | const items = options.parts.map(part=>part.dataSource);
3 | if(options.displayArea && options.startingContent){
4 | await solidUI.processComponentSubject(options.startingContent);
5 | }
6 | options.renderTab ||= (div,source)=>{
7 | const labels = (s)=>{
8 | for(let p of options.parts){
9 | if(p.dataSource===s)return p.label
10 | }
11 | }
12 | div.innerHTML = labels(source);
13 | }
14 | options.renderMain ||= async (div,source)=>{
15 | // div = inner main
16 | div.setAttribute('data-suic-area','tab-display');
17 | div.innerHTML = "";
18 | if(options.style) div.style="options.style";
19 | let c = await solidUI.processComponentSubject(source) ;
20 | div.appendChild( c );
21 | }
22 | const tabOptions = {
23 | items,
24 | backgroundColor : options.backgroundColor || solidUI.menuBackground,
25 | orientation : options.orientation,
26 | dom : options.dom,
27 | onClose : options.onClose,
28 | ordered : options.ordered,
29 | selectedTab: options.selectedTab,
30 | startEmpty : options.startEmpty,
31 | renderTab : options.renderTab,
32 | renderMain : options.renderMain,
33 | renderTabSettings : options.renderTabSettings,
34 | }
35 | return UI.tabs.tabWidget(tabOptions);
36 | }
37 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | // Configurations shared between all builds
4 | const common = {
5 | mode: 'production',
6 | entry: './src/index.js',
7 | output: {
8 | filename: 'solid-ui-components.bundle.js',
9 | library: 'solidUI',
10 | libraryExport: 'default',
11 | },
12 | devtool: 'source-map',
13 | }
14 |
15 | // Configurations specific to the window build
16 | const window = {
17 | ...common,
18 | name: 'window',
19 | output: {
20 | ...common.output,
21 | path: path.resolve(__dirname, 'dist'),
22 | libraryTarget: 'umd',
23 | },
24 | module: {
25 | rules: [
26 | {
27 | loader: 'babel-loader',
28 | exclude: /node_modules/,
29 | },
30 | ],
31 | },
32 | }
33 |
34 | // Configurations specific to the node build
35 | /*
36 | const node = {
37 | ...common,
38 | name: 'node',
39 | output: {
40 | ...common.output,
41 | path: path.resolve(__dirname, 'dist', 'node'),
42 | libraryTarget: 'commonjs2',
43 | },
44 | }
45 | */
46 | const resolve = {resolve:{ fallback: { "path": false } }}
47 | module.exports = [
48 | resolve,
49 | window
50 | ]
51 |
--------------------------------------------------------------------------------